Java基础知识面试题2

本文涉及的产品
访问控制,不限时长
简介: Java基础知识面试题2

static存在的主要意义

static是Java中的一个关键字,它可以用于修饰变量、方法和代码块。static存在的主要意义如下:


1. 共享内存空间。使用static修饰的变量和方法都属于类的静态成员,它们只会在内存中存在一份,被所有的对象共享。这样可以节省内存空间,避免重复创建对象和数据冗余。


2. 方便访问。使用static修饰的变量和方法可以通过类名直接访问,不需要先创建对象。这样可以方便地访问类的静态成员,避免了创建对象的麻烦。


3. 实现工具类和单例模式。使用static修饰的方法可以实现工具类和单例模式。工具类中的方法通常不需要创建对象,可以直接调用,而单例模式中的对象只需要创建一次,可以使用静态变量和静态方法来实现。


4. 初始化顺序。使用static修饰的代码块和变量会在类加载时被初始化,可以用于控制初始化顺序和实现一些复杂的初始化操作。


需要注意的是,static虽然具有很多优点,但是也有一些缺点。使用static会增加代码的耦合性和复杂性,可能会导致线程安全问题和内存泄漏问题。因此,在使用static时需要谨慎考虑,避免滥用。


1、为什么说static块可以用来优化程序性能?

static块可以用来优化程序性能的原因是因为它可以在类被加载时执行,而不需要等到类被实例化时才执行。这样可以避免在类被实例化时重复执行一些初始化操作,从而提高程序的性能。因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。


补充:static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。


2、static的独特之处

1、被static修饰的变量或者方法是独立于该类的任何对象,也就是说,这些变量和方法不属于任何一个实例对象,而是被类的实例对象所共享。


2、在该类被第一次加载的时候,就会去加载被static修饰的部分,而且只在类第一次使用时加载并进行初始化,注意这是第一次用就要初始化,后面根据需要是可以再次赋值的。


3、static变量值在类加载的时候分配空间,以后创建类对象的时候不会重新分配。赋值的话,是可以任意赋值的!


4、被static修饰的变量或者方法是优先于对象存在的,也就是说当一个类加载完毕之后,即便没有创建对象,也可以去访问。


3、static应用场景

1. 静态成员。使用static修饰的变量、方法和代码块都属于类的静态成员,它们只会在内存中存在一份,被所有的对象共享。这样可以节省内存空间,避免重复创建对象和数据冗余。


2. 静态方法。使用static修饰的方法可以直接通过类名调用,不需要先创建对象。静态方法不依赖于任何对象,可以被多个对象共享,因此可以用于实现工具类和单例模式。


3. 静态代码块。使用static修饰的代码块会在类被加载时执行,可以用于实现一些复杂的初始化操作,避免在类被实例化时重复执行一些初始化操作。


4. 静态内部类。使用static修饰的内部类属于类的静态成员,可以直接通过类名访问。静态内部类不依赖于外部类的实例,可以独立存在,因此可以用于实现一些工具类和辅助类。


4、static注意事项

1、静态只能访问静态。


2、非静态既可以访问非静态的,也可以访问静态的。


break ,continue ,return 的区别及作用

return

return关键字并不是专门用于跳出循环的,return的功能是结束一个方法。 一旦在循环体内执行到一个return语句,return语句将会结束该方法,循环自然也随之结束。与continue和break不同的是,return直接结束整个方法,不管这个return处于多少层循环之内。


public class ReturnTest
{
  public static void main(String[] args){
    // 一个简单的for循环
    for (int i = 0; i < 3 ; i++ ){
      System.out.println("i的值是" + i);
      if (i == 1){
        return;
      }
      System.out.println("return后的输出语句");
    }
  }
}


continue

continue的功能和break有点类似,区别是continue只是中止本次循环,接着开始下一次循环。而break则是完全中止循环。

public class ContinueTest
{
  public static void main(String[] args){
// 一个简单的for循环
    for (int i = 0; i < 3 ; i++ ){
        for (int j = 0; j < 3 ; j++ ){.
            System.out.println("j的值是" + j);
       if (j == 1){
         // 忽略本次,循环的剩下语句,就是除了j=1不打印以外其他的都打印
         continue;
       }
       System.out.println("continue后的输出语句");
    }
  }
}


break

break用于完全结束一个循环,跳出循环体。不管是哪种循环,一旦在循环体中遇到break,系统将完全结束循环,开始执行循环之后的代码。 break不仅可以结束其所在的循环,还可结束其外层循环。此时需要在break后紧跟一个标签,这个标签用于标识一个外层循环。Java中的标签就是一个紧跟着英文冒号(:)的标识符。且它必须放在循环语句之前才有作用。


public class BreakTest
{
  public static void main(String[] args){
    // 外层循环,outer作为标识符
    outer:
    for (int i = 0 ; i < 5 ; i++ ){
      // 内层循环
      for (int j = 0; j < 3 ; j++ ){
        System.out.println("i的值为:" + i + " j的值为:" + j);
        if (j == 1){
          // 跳出outer标签所标识的循环。
           break outer;
        }
      }
    }
  }
}

骚戴理解:注意break本身只能跳出一层循环,像上面的的第二层循环能跳出,但是不会跳出第一层循环,但是结合标识符就可以跳出多层嵌套循环

在 Java 中,如何跳出当前的多重嵌套循环

在Java中,要跳出当前的多重嵌套循环,可以使用标签(label)和break语句结合使用。例如:

outer: 
for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
        if (j == 5) {
            break outer;
        }
        System.out.println("i=" + i + ", j=" + j);
    }
}


骚戴理解:在上面的代码中,使用outer标签标记了外层循环,在内层循环中,当j等于5时,使用break outer语句跳出多重嵌套循环。当程序执行到这个语句时,会跳转到outer标签处,从而跳出多重嵌套循环。 注意上面的代码在执行到 `break outer;` 时,会立即跳出多重循环,不会继续执行之后的代码。


面向对象

面向对象和面向过程

面向过程的优缺点

优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素。

缺点:没有面向对象易维护、易复用、易扩展

面向对象的优缺点

优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护

缺点:性能比面向过程低


面向对象和面向过程的区别

面向对象和面向过程是两种不同的编程思想。面向过程是按照步骤一步一步地解决问题,强调的是数据和行为的分离;而面向对象则是将问题看作是由许多对象组成的,强调的是数据和行为的统一。面向过程的程序设计更加注重程序的执行过程,而面向对象的程序设计更加注重对象之间的交互。在面向对象的程序设计中,我们将问题看作是由许多对象组成的,每个对象都有自己的属性和方法,对象之间通过方法来进行交互,从而完成程序的功能。而在面向过程的程序设计中,我们则是按照步骤一步一步地解决问题,强调的是数据和行为的分离。


java中子类会继承父类的构造方法吗?

Java中的子类会默认继承父类的构造方法,但是子类的构造方法并不完全继承父类的构造方法。具体来说,子类构造方法会自动调用父类的无参构造方法,如果父类没有无参构造方法,则需要在子类的构造方法中显式调用父类的有参构造方法。如果子类的构造方法没有显式调用父类的构造方法,则编译器会自动在子类的构造方法中插入一条隐式的调用语句 `super();`,该语句会调用父类的无参构造方法。如果父类没有无参构造,然后子类又没有显性的引用父类的有参构造的话就会报错!


如果父类中有多个构造方法,子类可以选择调用其中一个构造方法,也可以在自己的构造方法中添加额外的参数,以便调用父类的有参构造方法。


需要注意的是,如果父类中的构造方法是private类型的,则子类无法继承该构造方法,因为private类型的构造方法只能在本类中访问,无法被子类继承和调用。


总之,Java中的子类会默认继承父类的构造方法,但需要注意构造方法的访问控制符以及在子类构造方法中是否显式调用了父类的构造方法。


java中子类会继承父类的private方法和属性吗?

Java中的子类不会继承父类的私有(private)方法和属性。私有方法和属性只能在本类中访问,无法被子类继承和访问。这是因为私有方法和属性的访问控制符是private,只能在本类中被访问,其他类无法访问。因此,子类无法继承父类的私有方法和属性。


如果父类中有一些私有方法和属性需要在子类中使用,可以将其改为protected类型,这样子类就可以继承和访问了。protected类型的方法和属性可以被子类继承和访问,同时也可以在同一包内的其他类中访问。


需要注意的是,如果父类中的方法和属性是default类型(即没有访问控制符),则子类可以继承和访问,但是只限于同一包内的子类。如果子类和父类不在同一包内,则无法继承和访问父类的default方法和属性。


面向对象的特征有哪些方面

1、抽象

抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。

其中Java 面向对象编程三大特性:封装 继承 多态

2、封装

Java的特性封装是通过使用访问控制符,我们可以将类的内部实现细节隐藏起来,只暴露出必要的接口,从而保证了数据的安全性和完整性。


在Java中,封装是通过访问控制符来实现的。Java提供了四种访问控制符:public、protected、private和default。其中,public表示公共的,可以在任何地方访问;protected表示受保护的,只能在当前类、同一包内的类和子类中访问;private表示私有的,只能在当前类中访问;default表示默认的,只能在同一包内的类中访问。


3、继承

继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承我们能够非常方便地复用以前的代码。

关于继承如下 3 点请记住:

1、子类拥有父类非 private 的属性和方法

2、子类可以拥有自己属性和方法,即子类可以对父类进行扩展。

3、子类可以用自己的方式实现父类的方法(重写)。


4、多态

Java的特性多态是指同一种行为或方法可以在不同的对象上具有不同的实现方式和表现形式。具体来说,多态性是指一个对象可以被看作是多种类型的实例,这些类型可以是它本身的类型,也可以是它的父类或接口的类型。


Java中的多态性主要通过两种方式实现:继承和接口。


通过继承,子类可以继承父类的方法和属性,同时也可以重写父类的方法,从而实现不同的行为。

通过接口,类可以实现多个接口,从而具有多种行为和表现形式。

在Java中,多态性的实现主要依赖于动态绑定机制。在程序运行时,系统会根据对象的实际类型来调用相应的方法,而不是根据变量的类型来调用方法。这样就可以实现同一种方法在不同对象上的不同实现方式和表现形式,从而实现多态性。


多态性的好处是可以提高程序的灵活性和可扩展性,同时也可以提高代码的可读性和可维护性。因此,在Java程序设计中,多态性是一个非常重要的特性。


什么是多态机制?Java语言是如何实现多态的?

什么是多态机制?

多态机制是一种面向对象编程的机制,多态是指同一种行为或方法可以在不同的对象上具有不同的实现方式和表现形式。具体来说,多态性是指一个对象可以被看作是多种类型的实例,这些类型可以是它本身的类型,也可以是它的父类或接口的类型。


Java语言是如何实现多态的?

Java语言是一种支持多态机制的编程语言,它通过继承和接口实现多态性。


Java中的多态性是通过动态绑定(Dynamic Binding)实现的。动态绑定是指在运行时根据对象的实际类型来确定调用哪个方法或属性。当一个方法被调用时,编译器并不知道实际调用的是哪个方法,而是在运行时根据对象的实际类型来确定调用哪个方法。这样就可以实现同一种方法在不同对象上的不同实现方式和表现形式,从而体现多态性。


具体来说,Java中的多态性主要通过两种方式实现:继承和接口。通过继承,子类可以继承父类的方法和属性,同时也可以重写父类的方法,从而实现不同的行为。通过接口,类可以实现多个接口,从而具有多种行为和表现形式。


在Java中,多态性的实现主要依赖于动态绑定机制。在程序运行时,系统会根据对象的实际类型来调用相应的方法,而不是根据变量的类型来调用方法。这样就可以实现同一种方法在不同对象上的不同实现方式和表现形式,从而实现多态性。


总之,Java中的多态机制是一种非常重要的面向对象编程的机制,它可以提高程序的灵活性和可扩展性,同时也可以提高代码的可读性和可维护性。


面向对象五大基本原则是什么

1、单一职责原则SRP(Single Responsibility Principle)

类的功能要单一,不能包罗万象,跟杂货铺似的。

2、开放封闭原则OCP(Open-Close Principle)

一个模块对于拓展是开放的,对于修改是封闭的

3、里式替换原则LSP(the Liskov Substitution Principle LSP)

子类可以替换父类出现在父类能够出现的任何地方。

4、依赖倒置原则DIP(the Dependency Inversion Principle DIP)

依赖倒置原则(Dependency Inversion Principle,简称DIP)是面向对象设计中的一条重要原则,它是SOLID原则中的一部分。它的核心思想是:高层模块不应该依赖于低层模块,二者都应该依赖于抽象,抽象不应该依赖于细节,而细节应该依赖于抽象。


这个原则的意思是,我们在设计类和模块时,应该尽量使用抽象类或接口来定义类之间的依赖关系,而不是使用具体的实现类。这样做的好处是,可以降低模块之间的耦合度,提高代码的可维护性和可扩展性。同时,也可以提高代码的重用性和测试性。


具体来说,依赖倒置原则可以通过以下几个方面来实现:


1. 高层模块不应该依赖于低层模块:这意味着我们应该尽量避免在高层模块中直接使用低层模块的具体实现类,而应该使用抽象类或接口来定义依赖关系。


2. 二者都应该依赖于抽象:这意味着我们应该尽量使用抽象类或接口来定义类之间的依赖关系,而不是使用具体的实现类。


3. 抽象不应该依赖于细节:这意味着我们应该尽量避免在抽象类或接口中使用具体的实现类,而应该将细节留给具体的实现类去处理。


4. 细节应该依赖于抽象:这意味着我们应该尽量使用抽象类或接口来定义类之间的依赖关系,而具体的实现类应该依赖于抽象类或接口。


总之,依赖倒置原则是一条非常重要的面向对象设计原则,它可以帮助我们设计出更加灵活、可维护、可扩展和可测试的代码。


5、接口分离原则ISP(the Interface Segregation Principle ISP)

接口分离原则(Interface Segregation Principle,简称ISP)是面向对象设计中的一条重要原则,它是SOLID原则中的一部分。它的核心思想是:一个类不应该依赖于它不需要的接口,一个类应该尽量少地依赖于其他类。


这个原则的意思是,我们在设计接口时,应该尽量将接口拆分成多个小的、专门的接口,而不是设计一个大而全的接口。这样做的好处是,可以降低类之间的耦合度,提高代码的可维护性和可扩展性。同时,也可以提高代码的重用性和灵活性。


具体来说,接口分离原则可以通过以下几个方面来实现:


1. 将接口拆分成多个小的、专门的接口:这意味着我们应该尽量将接口中的方法拆分成多个小的、专门的接口,而不是设计一个大而全的接口。


2. 避免接口过于臃肿:这意味着我们应该尽量避免在接口中定义过多的方法,而应该将方法拆分成多个小的、专门的接口。


3. 接口与实现相分离:这意味着我们应该尽量将接口与实现相分离,将接口定义在独立的模块中,而具体的实现类则实现接口。


4. 不强制实现不需要的接口:这意味着我们应该尽量避免在一个类中实现不需要的接口,而应该只实现该类需要的接口。


总之,接口分离原则是一条非常重要的面向对象设计原则,它可以帮助我们设计出更加灵活、可维护、可扩展和可测试的代码。


抽象类和接口的对比

抽象类和接口都是Java中实现抽象的机制,但是它们有一些异同之处。


相同点:


1. 都不能被实例化,只能被继承或实现。


2. 都可以包含抽象方法,需要子类或实现类去实现。


3. 都可以包含具体的方法实现。


4. 都可以用来实现多态性。


不同点:


1. 抽象类可以包含抽象方法和具体方法,而接口只能包含抽象方法。


2. 一个类只能继承一个抽象类,但是可以实现多个接口。


3. 抽象类可以有构造方法,而接口没有构造方法。


4. 抽象类的子类可以覆盖父类的方法,也可以不覆盖,而实现接口的类必须实现接口中的所有方法。


5. 抽象类可以有成员变量,而接口只能有常量。


6. 抽象类的访问修饰符可以是public、protected或默认的,而接口的访问修饰符只能是public。


7. 抽象类用于表示一种“is-a”的关系,即子类是父类的一种特殊类型,而接口用于表示一种“has-a”的关系,即类具有某种能力或特征。


总之,抽象类和接口都是Java中实现抽象的机制,它们都有自己的优缺点和适用场景,我们需要根据具体的需求来选择使用哪种方式。

java中接口的方法能不能有方法体?

在Java 8之前,接口中的方法都是抽象方法,不能有方法体。但是,从Java 8开始,接口中可以定义默认方法(default method)和静态方法(static method),这两种方法都可以有方法体。


默认方法是指在接口中定义的有方法体的方法,可以被实现该接口的类直接继承或重写。默认方法的关键字是default,例如:


public interface MyInterface {
    default void myMethod() {
        System.out.println("This is a default method.");
    }
}

静态方法是指在接口中定义的有方法体的静态方法,可以直接通过接口名调用。静态方法的关键字是static,例如:

public interface MyInterface {
    static void myStaticMethod() {
        System.out.println("This is a static method.");
    }
}

需要注意的是,接口中的默认方法和静态方法都有方法体,但是抽象方法没有方法体。默认方法和静态方法的出现使得接口的功能更加强大,可以更好地支持代码的复用和扩展。


普通类和抽象类有哪些区别?

普通类和抽象类的主要区别在于:


1. 实例化:普通类可以被直接实例化,而抽象类不能被直接实例化,只能被继承。


2. 抽象方法:普通类中不能包含抽象方法,而抽象类中可以包含抽象方法。


3. 方法实现:普通类中的方法必须有具体的实现,而抽象类中的抽象方法没有具体的实现,需要子类去实现。


4. 继承:普通类可以被其他类继承,而抽象类只能被继承,不能被实例化。


5. 关系:普通类表示一种具体的对象,而抽象类表示一种抽象的概念或模板。


6. 使用:普通类通常用于封装数据和行为,而抽象类通常用于定义一些通用的行为和属性,以便子类继承和实现。


总之,普通类和抽象类都是Java中的类,它们有自己的特点和适用场景。我们需要根据具体的需求来选择使用哪种类型的类。


骚戴理解:需要注意的是抽象类里面可以有抽象方法和非抽象方法(也就是有方法体的方法),所以抽象类里的方法不一定都是抽象方法,但是如果一个类里有抽象方法,那么这个类一定是抽象类


抽象类能使用 final 修饰吗?

不能,定义抽象类就是让其他类继承的,如果定义为 final 该类就不能被继承,这样彼此就会产生矛盾,所以 final 不能修饰抽象类

相关实践学习
消息队列+Serverless+Tablestore:实现高弹性的电商订单系统
基于消息队列以及函数计算,快速部署一个高弹性的商品订单系统,能够应对抢购场景下的高并发情况。
云安全基础课 - 访问控制概述
课程大纲 课程目标和内容介绍视频时长 访问控制概述视频时长 身份标识和认证技术视频时长 授权机制视频时长 访问控制的常见攻击视频时长
目录
相关文章
|
1月前
|
安全 架构师 Java
Java大厂面试高频:Collection 和 Collections 到底咋回答?
Java中的`Collection`和`Collections`是两个容易混淆的概念。`Collection`是集合框架的根接口,定义了集合的基本操作方法,如添加、删除等;而`Collections`是一个工具类,提供了操作集合的静态方法,如排序、查找、同步化等。简单来说,`Collection`关注数据结构,`Collections`则提供功能增强。通过小王的面试经历,我们可以更好地理解这两者的区别及其在实际开发中的应用。希望这篇文章能帮助你掌握这个经典面试题。
51 4
|
3月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
140 2
|
1月前
|
Java 程序员
Java社招面试中的高频考点:Callable、Future与FutureTask详解
大家好,我是小米。本文主要讲解Java多线程编程中的三个重要概念:Callable、Future和FutureTask。它们在实际开发中帮助我们更灵活、高效地处理多线程任务,尤其适合社招面试场景。通过 Callable 可以定义有返回值且可能抛出异常的任务;Future 用于获取任务结果并提供取消和检查状态的功能;FutureTask 则结合了两者的优势,既可执行任务又可获取结果。掌握这些知识不仅能提升你的编程能力,还能让你在面试中脱颖而出。文中结合实例详细介绍了这三个概念的使用方法及其区别与联系。希望对大家有所帮助!
183 60
|
13天前
|
Java 程序员 开发者
Java社招面试题:一个线程运行时发生异常会怎样?
大家好,我是小米。今天分享一个经典的 Java 面试题:线程运行时发生异常,程序会怎样处理?此问题考察 Java 线程和异常处理机制的理解。线程发生异常,默认会导致线程终止,但可以通过 try-catch 捕获并处理,避免影响其他线程。未捕获的异常可通过 Thread.UncaughtExceptionHandler 处理。线程池中的异常会被自动处理,不影响任务执行。希望这篇文章能帮助你深入理解 Java 线程异常处理机制,为面试做好准备。如果你觉得有帮助,欢迎收藏、转发!
72 14
|
16天前
|
安全 Java 程序员
Java 面试必问!线程构造方法和静态块的执行线程到底是谁?
大家好,我是小米。今天聊聊Java多线程面试题:线程类的构造方法和静态块是由哪个线程调用的?构造方法由创建线程实例的主线程调用,静态块在类加载时由主线程调用。理解这些细节有助于掌握Java多线程机制。下期再见! 简介: 本文通过一个常见的Java多线程面试题,详细讲解了线程类的构造方法和静态块是由哪个线程调用的。构造方法由创建线程实例的主线程调用,静态块在类加载时由主线程调用。理解这些细节对掌握Java多线程编程至关重要。
48 13
|
1月前
|
算法 安全 Java
Java线程调度揭秘:从算法到策略,让你面试稳赢!
在社招面试中,关于线程调度和同步的相关问题常常让人感到棘手。今天,我们将深入解析Java中的线程调度算法、调度策略,探讨线程调度器、时间分片的工作原理,并带你了解常见的线程同步方法。让我们一起破解这些面试难题,提升你的Java并发编程技能!
84 16
|
1月前
|
Java 程序员 调度
Java 高级面试技巧:yield() 与 sleep() 方法的使用场景和区别
本文详细解析了 Java 中 `Thread` 类的 `yield()` 和 `sleep()` 方法,解释了它们的作用、区别及为什么是静态方法。`yield()` 让当前线程释放 CPU 时间片,给其他同等优先级线程运行机会,但不保证暂停;`sleep()` 则让线程进入休眠状态,指定时间后继续执行。两者都是静态方法,因为它们影响线程调度机制而非单一线程行为。这些知识点在面试中常被提及,掌握它们有助于更好地应对多线程编程问题。
66 9
|
1月前
|
安全 Java 程序员
Java面试必问!run() 和 start() 方法到底有啥区别?
在多线程编程中,run和 start方法常常让开发者感到困惑。为什么调用 start 才能启动线程,而直接调用 run只是普通方法调用?这篇文章将通过一个简单的例子,详细解析这两者的区别,帮助你在面试中脱颖而出,理解多线程背后的机制和原理。
70 12
|
1月前
|
监控 Dubbo Java
Java Dubbo 面试题
Java Dubbo相关基础面试题
|
1月前
|
SQL Java 数据库连接
Java MyBatis 面试题
Java MyBatis相关基础面试题

热门文章

最新文章