所有的面试题目全部整理自网络,若有错误可联系作者改正。
题目信息和Java面试题库Pro小程序保持一致,小程序方便移动端刷题,该网页方便在PC刷题。
所有的建议和意见均可通过小程序Java面试题库Pro找到客服反馈或者添加作者的联系方式。
1、什么是跨平台性?原理是什么
所谓跨平台性,是指java语言编写的程序,一次编译后,可以在多个系统平台上运行。
实现原理:Java程序是通过java虚拟机在系统平台上运行的,只要该系统可以安装相应的java虚拟机,该系统就可以运行java程序。
2、什么是字节码?采用字节码的最大好处是什么
Java源代码经过虚拟机编译器编译后产生的文件(即扩展为.class的文件),它不面向任何特定的处理器,只面向虚拟机。
3、采用字节码的好处
Java语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以Java程序运行时比较高效,而且,由于字节码并不专对一种特定的机器,因此,Java程序无须重新编译便可在多种不同的计算机上运行。
4、OracleJDK 和 OpenJDK 的对比
1、Oracle JDK版本将每三年发布一次,而OpenJDK版本每三个月发布一次;
2、OpenJDK 是一个参考模型并且是完全开源的,而Oracle JDK是OpenJDK的一个实现,并不是完全开源的;
3、Oracle JDK 比 OpenJDK 更稳定。OpenJDK和Oracle JDK的代码几乎相同,但Oracle JDK有更多的类和一些错误修复。因此,如果您想开发企业/商业软件,我建议您选择Oracle JDK,因为它经过了彻底的测试和稳定。某些情况下,有些人提到在使用OpenJDK 可能会遇到了许多应用程序崩溃的问题,但是,只需切换到Oracle JDK就可以解决问题;
4、在响应性和JVM性能方面,Oracle JDK与OpenJDK相比提供了更好的性能;
5、Oracle JDK不会为即将发布的版本提供长期支持,用户每次都必须通过更新到最新版本获得支持来获取最新版本;
6、Oracle JDK根据二进制代码许可协议获得许可,而OpenJDK根据GPL v2许可获得许可。
5、什么是面向对象
面向对象程序设计是以建立模型体现出来的抽象思维过程和面向对象的方法。我们可以将某个事物抽象出来,赋予它自己的特征,并且可以针对这个事物进行相应的操作,以及规定与其他对象之间的关系。可以降低代码的耦合度,使程序更加灵活。
6、多态的实现需要哪些条件
Java实现多态有三个必要条件:继承、重写、向上转型。
继承:在多态中必须存在有继承关系的子类和父类。
重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
向上转型:在多态中需要将子类的引用赋给父类对象。
7、面向对象五大基本原则是什么
单一职责原则SRP(Single Responsibility Principle):类的功能要单一,不能包罗万象,跟杂货铺似的。
开放封闭原则OCP(Open-Close Principle):一个模块对于拓展是开放的,对于修改是封闭的,想要增加功能热烈欢迎,想要修改,哼,一万个不乐意。
里式替换原则LSP(the Liskov Substitution Principle LSP):子类可以替换父类出现在父类能够出现的任何地方。比如你能代表你爸去你姥姥家干活。哈哈~~
依赖倒置原则DIP(the Dependency Inversion Principle DIP):高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。抽象不应该依赖于具体实现,具体实现应该依赖于抽象。就是你出国要说你是中国人,而不能说你是哪个村子的。比如说中国人是抽象的,下面有具体的xx省,xx市,xx县。你要依赖的抽象是中国人,而不是你是xx村的。
接口分离原则ISP(the Interface Segregation Principle ISP):设计时采用多个与特定客户类有关的接口比采用一个通用的接口要好。就比如一个手机拥有打电话,看视频,玩游戏等功能,把这几个功能拆分成不同的接口,比在一个接口里要好的多。
8、什么是值传递和引用传递
值传递:是对基本型变量而言的,传递的是该变量的一个副本,改变副本不影响原变量。
引用传递:一般是对于对象型变量而言的,传递的是该对象地址的一个副本,但是该副本和原对象指向的是内存中的同一个地址,改变副本会影响对象。
9、抽象类和接口的区别
抽象类的特点:
抽象类使用 abstract 关键字声明。
抽象类中可以包含普通方法和抽象方法,抽象方法不能有具体的代码实现。
抽象类需要使用 extends 关键字实现继承。
抽象类不能直接实例化。
抽象类中属性控制符无限制,可以定义 private 类型的属性。
接口的特点:
JDK 8 中接口可以定义 static 和 default 方法,并且这两种方法可以包含具体的代码实现。
实现接口要使用 implements 关键字。
接口不能直接实例化。
接口中定义的变量默认为 public static final 类型。
子类可以不重写接口中的 static 和 default 方法,不重写的情况下,默认调用的是接口的方法实现。
抽象类和接口的区别:
定义的关键字不同。
子类继承或实现关键字不同。
类型扩展不同:抽象类是单继承,而接口是多继承。
方法访问控制符:抽象类无限制,只是抽象类中的抽象方法不能被 private 修饰;而接口有限制,接口默认的是 public 控制符。
属性方法控制符:抽象类无限制,而接口有限制,接口默认的是 public 控制符。
方法实现不同:抽象类中的普通方法必须有实现,抽象方法必须没有实现;而接口中普通方法不能有实现,但在 JDK 8 中的 static 和 defualt 方法必须有实现。
静态代码块的使用不同:抽象类可以有静态代码块,而接口不能有。
10、什么是不可变对象
不可变对象指对象一旦被创建,状态就不能再改变。任何修改都会创建一个新的对象,如 String、Integer及其它包装类。
11、静态变量和实例变量的区别
1、存储区域不同:静态变量存储在方法区,实例变量存储在堆中,会被垃圾回收释放。
2、关联不同:静态变量与类相关,实例变量与对象相关。
3、生命周期不同:静态变量在类启动时就分配内存,实例变量在被对象调用后才分配内存,调用结束时内存释放。
12、switch 是否能作用在 byte 上,是否能作用在 long 上,是否能作用在 String 上
在 Java 5 以前,switch(expr)中,expr 只能是 byte、short、char、int。
从 Java 5 开始,Java 中引入了枚举类型,expr 也可以是 enum 类型。
从 Java 7 开始,expr 还可以是字符串(String),但是长整型(long)在目前所有的版本中都是不可以的。
13、用最有效率的方法计算 2 乘以 8
2 << 3 (左移 3 位相当于乘以 2 的 3 次方,右移 3 位相当于除以 2 的 3 次方)。
14、short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗
对于 short s1 = 1; s1 = s1 + 1;由于 1 是 int 类型,因此 s1+1 运算结果也是 int型,需要强制转换类型才能赋值给 short 型。
而 short s1 = 1; s1 += 1;可以正确编译,因为 s1+= 1 相当于 s1 = (short(s1 + 1)) 其中有隐含的强制类型转换。
15、final有哪些用法
1.被final修饰的类不可以被继承
2.被final修饰的方法不可以被重写
3.被final修饰的变量不可以被改变。如果修饰引用,那么表示引用不可变,引用指向的内容可变。
4.被final修饰的方法,JVM会尝试将其内联,以提高运行效率
5.被final修饰的常量,在编译阶段会存入常量池中。
回答出编译器对final域要遵守的两个重排序规则更好:
1.在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序。
2.初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操作之间不能重排序。
16、final finally finalize区别
final可以修饰类、变量、方法,修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、修饰变量表示该变量是一个常量不能被重新赋值。
finally一般作用在try-catch代码块中,在处理异常的时候,通常我们将一定要执行的代码方法finally代码块中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码。
finalize是一个方法,属于Object类的一个方法,而Object类是所有类的父类,该方法一般由垃圾回收器来调用,当我们调用System.gc() 方法的时候,由垃圾回收器调用finalize(),回收垃圾,一个对象是否可回收的最后判断。
17、static存在的主要意义
static的主要意义是在于创建独立于具体对象的域变量或者方法。以致于即使没有创建对象,也能使用属性和调用方法!
static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。
为什么说static块可以用来优化程序性能,是因为它的特性:只会在类加载的时候执行一次。因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。
18、a==b与a.equals(b)有什么区别
如果 a 和 b 都是对象,则 a==b 是比较两个对象的引用,只有当 a 和 b 指向的是堆中的同一个对象才会返回 true。
a.equals(b) 是进行逻辑比较,所以通常需要重写该方法来提供逻辑一致性的比较。例如,String 类重写 equals() 方法,所以可以用于两个不同对象,但是包含的字母相同的比较。
19、什么是内部类,内部类的分类有哪些
在Java中,可以将一个类的定义放在另外一个类的定义内部,这就是内部类。
内部类本身就是类的一个属性,与其他属性定义方式一致。
内部类可以分为四种:成员内部类、局部内部类、匿名内部类和静态内部类。
20、内部类的优点
一个内部类对象可以访问创建它的外部类对象的内容,包括私有数据!
内部类不为同一包的其他类所见,具有很好的封装性;
内部类有效实现了“多重继承”,优化 java 单继承的缺陷。
匿名内部类可以很方便的定义回调。
21、BIO,NIO,AIO 有什么区别
BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。
NIO:Non IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。
AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。
22、什么是反射机制
简单说,反射机制指得是程序在运行时能够获取自身的信息。在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息。
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
|
23、反射机制的应用场景有哪些
反射是框架设计的灵魂,在我们平时的项目开发过程中,基本上很少会直接使用到反射机制,但这不能说明反射机制没有用,实际上有很多设计、开发都与反射机制有关,例如模块化的开发,通过反射去调用对应的字节码。动态代理设计模式也采用了反射机制,还有我们日常使用的 Spring/Hibernate 等框架也大量使用到了反射机制。
举例:
(1)、我们在使用JDBC连接数据库时使用Class.forName()通过反射加载数据库的驱动程序;
(2)、Spring框架也用到很多反射机制,最经典的就是xml的配置模式。Spring 通过 XML 配置模式装载 Bean 的过程:
1) 将程序内所有 XML 或 Properties 配置文件加载入内存中;
2) Java类里面解析xml或properties里面的内容,得到对应实体类的字节码字符串以及相关的属性信息;
3) 使用反射机制,根据这个字符串获得某个类的Class实例;
4) 动态配置实例的属性
24、Java获取反射的三种方法
1.通过new对象实现反射机制
2.通过路径实现反射机制
3.通过类名实现反射机制
|
25、反射中,Class.forName 和 ClassLoader 区别
java中class.forName()和classLoader都可用来对类进行加载。class.forName()前者除了将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块。而classLoader只干一件事情,就是将.class文件加载到jvm中,不会执行static中的内容,只有在newInstance才会去执行static块。
26、什么是动态代理
代理类在程序运行时创建的代理方式被成为 动态代理。 也就是说,这种情况下,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。
相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类的函数。
27、Java动态代理的两种实现方法
jdk动态代理是由java内部的反射机制来实现的,cglib动态代理底层则是借助asm来实现的。
jdk动态代理是jdk原生就支持的一种代理方式,它的实现原理,就是通过让target类和代理类实现同一接口,代理类持有target对象,来达到方法拦截的作用,这样通过接口的方式有两个弊端,一个是必须保证target类有接口,第二个是如果想要对target类的方法进行代理拦截,那么就要保证这些方法都要在接口中声明,实现上略微有点限制。
Cglib是一个优秀的动态代理框架,它的底层使用ASM在内存中动态的生成被代理类的子类,使用CGLIB即使代理类没有实现任何接口也可以实现动态代理功能。CGLIB具有简单易用,它的运行速度要远远快于JDK的Proxy动态代理:
28、什么是 Java 序列化
序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。
可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。
序列化是为了解决在对对象流进行读写操作时所引发的问题。
反序列化的过程,则是和序列化相反的过程。
另外,我们不能将序列化局限在 Java 对象转换成二进制数组,例如说,我们将一个 Java 对象,转换成 JSON 字符串,或者 XML 字符串,这也可以理解为是序列化。
29、Java 序列化中,如果有些字段不想进行序列化怎么办
对于不想进行序列化的变量,使用 transient 关键字修饰,当对象被序列化时,阻止实例中那些用此关键字修饰的的变量序列化。
当对象被反序列化时,被 transient 修饰的变量值不会被持久化和恢复,transient 只能修饰变量,不能修饰类和方法。
30、String有哪些特性
不变性:String 是只读字符串,是一个典型的 immutable 对象,对它进行任何操作,其实都是创建一个新的对象,再把引用指向该对象。不变模式的主要作用在于当一个对象需要被多线程共享并频繁访问时,可以保证数据的一致性。
常量池优化:String 对象创建之后,会在字符串常量池中进行缓存,如果下次创建同样的对象时,会直接返回缓存的引用。
final:使用 final 来定义 String 类,表示 String 类不能被继承,提高了系统的安全性。
31、String str=”i”与 String str=new String(“i”)一样吗
不一样,因为内存的分配方式不一样。String str=”i”的方式,java 虚拟机会将其分配到常量池中;而 String str=new String(“i”) 则会被分到堆内存中。
32、String s = new String(“xyz”);创建了几个字符串对象
如果字符串常量池中存在 “xyz”,则只会创建一个对象,即堆中 new 出来的新对象。
如果字符串常量池中不存在 “xyz”,则会创建两个对象,一个是字符串常量池的 “xyz”,一个是用 new 创建在堆上的对象。
33、在使用 HashMap 的时候,用 String 做 key 有什么好处
HashMap 内部实现是通过 key 的 hashcode 来确定 value 的存储位置,因为字符串是不可变的,所以当创建字符串时,它的 hashcode 被缓存下来,不需要再次计算,所以相比于其他对象更快。
34、String、StringBuffer、StringBuilder区别
String 是字符串常量,final 修饰;
StringBuffer 字符串变量(线程安全);
StringBuilder 字符串变量(线程不安全);
String和StringBuffer
1、String和StringBuffer 主要区别是性能:String 是不可变对象,每次对 String 类型进行操作都等同于产生了一个新的 String 对象,然后指向新的 String 对象。所以尽量不在对 String 进行大量的拼接操作,否则会产生很多临时对象,导致 GC 开始工作,影响系统性能。
2、StringBuffer 是对对象本身操作,而不是产生新的对象,因此在有大量拼接的情况下,我们建议使用 StringBuffer。
3、VM会对String拼接做一定的优化:String s=“This is only ”+”simple”+”test” 会被虚拟机直接优化成 String s=“This is only simple test”,此时就不存在拼接过程。
StringBuffer 和 StringBuilder
StringBuffer 是线程安全的可变字符串,其内部实现是可变数组。StringBuilder 是 jdk 1.5 新增的,其功能和 StringBuffer 类似,但是非线程安全。因此,在没有多线程问题的前提下,使用 StringBuilder 会取得更好的性能。
35、Overload和Override的区别
方法重写Overriding和方法重载Overloading是Java多态性的不同表现。
重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。
如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。
如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。
Overloading的方法是可以改变返回值的类型。
36、Java有哪些数据类型
基本数据类型
整数类型(byte,short,int,long)
浮点类型(float,double)
字符型(char)
布尔型(boolean)
引用数据类型
类(class)
接口(interface)
数组([])
37、switch是否能作用在byte上,是否能作用在long上,是否能作用在String上
在 Java5 以前,switch(expr) 表达式中,expr 只能是 byte、short、char、int。
从 Java5 开始,Java 中引入了枚举类型,expr 也可以是 enum 类型。
从 Java7 开始,expr 还可以是字符串(String),但是长整型(long)在目前所有的版本中都是不可以的。
38、Math.round(11.5) 等于多少?Math.round(-11.5)等于多少
Math.round(11.5)的返回值是 12,Math.round(-11.5)的返回值是-11,四舍五入的原理是在参数上加0.5然后进行下取整。
39、表达式 float f = 3.4 是否正确
不正确,3.4 是双精度数,将双精度型(double)赋值给浮点型(float)属于下转型(down-casting,也称为窄化)会造成精度损失,因此需要强制类型转换 float f = (float) 3.4 或者写成 float f = 3.4F。
40、访问修饰符 public、private、protected以及不写(默认)时的区别
private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
default (即缺省,什么也不写,不使用任何关键字): 在同一包内可见。使用对象:类、接口、变量、方法。
protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
public : 对所有类可见。使用对象:类、接口、变量、方法。
41、运算符&和&&的区别
&运算符有两种用法:
(1) 按位与
(2) 逻辑与
&&运算符是短路与运算,逻辑与跟短路与的差别是非常巨大的,二者都要求运算符左右两端的布尔值都是true 整个表达式的值才是 true。
&&之所以称为短路运算,是因为如果&&左边的表达式的值是 false,右边的表达式会被直接短路掉,不会进行运算。
注意:逻辑或运算符(|)和短路或运算符(||)的差别也是如此。
42、3*0.1 == 0.3 返回值是什么
返回false,因为有些浮点数不能完全精确的表示出来。
43、a = a+b 与 a += b 有什么区别吗
+= 操作符会进行隐式自动类型转换,此处 a +=b 隐式的将加操作的结果类型强制转换为持有结果的类型,而 a = a+b 则不会自动进行类型转换。
44、如何将byte转为String
可以使用 String 接收 byte[] 参数的构造器来进行转换,需要注意的点是要使用正确的编码,否则会使用平台默认编码,这个编码可能跟原来的编码相同,也可能不同。
45、可以将 int 强转为 byte 类型吗?会产生什么问题
可以做强制转换,但是Java中int是32位的而byte是8位的,所以如果进行强制转换,int类型的高24位将会被丢弃,byte 类型的范围是从-128到127。
46、Java 有没有 goto
goto 是 Java 中的保留字,在目前版本的 Java 中没有使用。
47、final 关键字有什么用
用于修饰类、属性和方法
被final修饰的类不可以被继承
被final修饰的方法不可以被重写
被final修饰的变量不可以被改变,被final修饰不可变的是变量的引用,而不是引用指向的内容,引用指向的内容是可以改变的。
48、this 关键字的用法
this 是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针。
this 的用法大体可以分为3种:
1.普通的直接引用,this相当于是指向当前对象本身。
2.形参与成员名字重名,用 this 来区分:
|
3.引用本类的构造函数:
|
49、super 关键字的用法
super可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类。
super有三种用法:
1.普通的直接引用,与this类似,super相当于是指向当前对象的父类的引用,这样就可以用super.xxx来引用父类的成员。
2.子类中的成员变量或方法与父类中的成员变量或方法同名时,用super进行区分:
|
3.引用父类构造函数
super(参数): 调用父类中的某一个构造函数(应该为构造函数中的第一条语句)。
this(参数): 调用本类中另一种形式的构造函数(应该为构造函数中的第一条语句)。
50、this 与 super 的区别
super:它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函数,基类与派生类中有相同成员定义时如:super.变量、super.成员函数名(实参)。
this:它代表当前对象名(在程序中易产生二义性之处,应使用this来指明当前对象;如果函数的形参与类中的成员数据同名,这时需用this来指明成员变量名)。
super() 和 this() 类似,区别是 super() 在子类中调用父类的构造方法,this() 在本类内调用本类的其它构造方法。
super() 和 this() 均需放在构造方法内第一行。
可以用this调用一个构造器,但不能调用两个。
this 和 super 不能同时出现在一个构造函数里面,因为 this 必然会调用其它的构造函数,其它的构造函数必然也会有 super 语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。
this() 和 super() 都指的是对象,所以均不可以在 static 环境中使用。包括:static变量、static方法、static语句块。
从本质上讲,this是一个指向本对象的指针,然而super是一个Java关键字。
51、static的特点
1、被static修饰的变量或者方法是独立于该类的任何对象,也就是说,这些变量和方法不属于任何一个实例对象,而是被类的实例对象所共享。
2、在该类被第一次加载的时候,就会去加载被static修饰的部分,而且只在类第一次使用时加载并进行初始化,注意这是第一次用就要初始化,后面根据需要是可以再次赋值的。
3、static变量值在类加载的时候分配空间,以后创建类对象的时候不会重新分配。赋值的话,是可以任意赋值的!
4、被static修饰的变量或者方法是优先于对象存在的,也就是说当一个类加载完毕之后,即便没有创建对象,也可以去访问。
52、break 、continue、return 的区别及作用
break 跳出当前循环,不再执行循环(结束当前的循环体)
continue 跳出本次循环,继续执行下次循环(结束正在执行的循环 进入下一个循环条件)
return 程序返回,不再执行下面的代码(结束当前的方法 直接返回)
53、在 Java 中,如何跳出当前的多重嵌套循环
在Java中,要想跳出多重循环,可以在外面的循环语句前定义一个标号,然后在里层循环体的代码中使用带有标号的break 语句,即可跳出外层循环。例如:
|
54、抽象类和接口的对比
抽象类是用来捕捉子类的通用特性的。接口是抽象方法的集合。
从设计层面来说,抽象类是对类的抽象,是一种模板设计;接口是行为的抽象,是一种行为的规范。
相同点
接口和抽象类都不能实例化
都位于继承的顶端,用于被其他实现或继承
都包含抽象方法,其子类都必须覆写这些抽象方法
不同点
暂时省略。。。
接口和抽象类各有优缺点,在接口和抽象类的选择上,必须遵守这样一个原则:
行为模型应该总是通过接口而不是抽象类定义,所以通常是优先选用接口,尽量少用抽象类。
选择抽象类的时候通常是如下情况:需要定义子类的行为,又要为子类提供通用的功能。
55、普通类和抽象类有哪些区别
普通类不能包含抽象方法,抽象类可以包含抽象方法。
抽象类不能直接实例化,普通类可以直接实例化。
56、抽象类能使用 final 修饰吗
不能,定义抽象类就是让其他类继承的,如果定义为 final 该类就不能被继承,这样彼此就会产生矛盾,所以 final 不能修饰抽象类。
57、Java支持多继承么
Java 中类不支持多继承,只支持单继承(即一个类只有一个父类)。
但是 Java 中的接口支持多继承,即一个子接口可以有多个父接口。(接口的作用是用来扩展对象的功能,一个子接口继承多个父接口,说明子接口扩展了多个功能,当类实现接口时,类就扩展了相应的功能)。
58、成员变量与局部变量的区别有哪些
定义位置不同
成员变量:定义在方法外部,类的内部。
局部变量:定义在方法中。
作用域
成员变量:针对整个类有效。
局部变量:只在某个范围内有效。(一般指的就是方法,离他最近最近的{}内)
存储位置
成员变量:随着对象的创建而存在,随着对象的消失而消失,存储在堆内存中。
局部变量:在方法被调用,或者语句被执行的时候存在,存储在栈内存中。
生命周期
成员变量:随着对象的创建而存在,随着对象的消失而消失。
局部变量:当方法调用完,或者语句结束后,就自动释放。
初始值
成员变量:有默认初始值。
局部变量:没有默认初始值,使用前必须赋值。
59、为什么在Java中定义一个不做事且没有参数的构造方法
Java程序在执行子类的构造方法之前,如果没有用super()来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用super()来调用父类中特定的构造方法,则编译时将发生错误,因为Java程序在父类中找不到没有参数的构造方法可供执行,解决办法是在父类里加上一个不做事且没有参数的构造方法。
60、在调用子类构造方法之前会先调用父类没有参数的构造方法的其目是什么
帮助子类做一些初始化工作。
61、一个类的构造方法的作用是什么?若一个类没有声明构造方法,该程序能正确执行吗
主要作用是完成对类对象的初始化工作,没有声明构造方法程序可以执行,因为一个类即使没有声明构造方法也会有默认的不带参数的构造方法。
62、静态变量和实例变量区别
静态变量: 静态变量不属于任何实例对象,是属于类的,所以在内存中只会有一份,在类的加载过程中,JVM 只为静态变量分配一次内存空间。
实例变量: 每次创建对象,都会为每个对象分配成员变量内存空间,实例变量是属于实例对象的,在内存中,创建几次对象,就有几份成员变量。
63、静态方法和实例方法有何不同
调用方式:在外部调用静态方法时,可以使用”类名.方法名”的方式,也可以使用”对象名.方法名”的方式。而实例方法只能使用”对象名.方法名”的方式。也就是说,调用静态方法可以无需创建对象。
访问对象和方法:静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制。
64、什么是内部类?内部类的分类有哪些
在Java中,可以将一个类的定义放在另外一个类的定义内部,这就是内部类。内部类本身就是类的一个属性,与其他属性定义方式一致。
内部类可以分为四种:成员内部类、局部内部类、匿名内部类和静态内部类。
65、equals() 和 hashcode() 的关系
hashCode() 是 Object 类的一个方法,返回一个哈希值。
如果两个对象根据 equal() 方法比较相等,那么调用这两个对象的 hashCode() 方法必须产生相同的哈希值。
如果两个对象根据 eqaul() 方法比较不相等,那么产生的哈希值不一定相等(会存在相等的情况)。
66、hashCode() 方法有什么用
将对象放入到集合中时,首先判断要放入对象的 hashcode 是否已经在集合中存在,不存在则直接放入集合。如果 hashcode 相等,然后通过 equal() 方法判断要放入对象与集合中的任意对象是否相等:如果 equal() 判断不相等,直接将该元素放入集合中,否则不放入。
67、有没有可能两个不相等的对象有相同的hashcode
有可能,两个不相等的对象可能会有相同的 hashcode 值,这就是为什么在 hashmap 中会有冲突,如果两个对象相等,必须有相同的hashcode 值,反之不成立。
68、a == b 与 a.equals(b) 有什么区别
如果 a 和 b 都是对象,则 a==b 是比较两个对象的引用,只有当 a 和 b 指向的是堆中的同一个对象才会返回 true,而 a.equals(b) 是进行逻辑比较,所以通常需要重写该方法来提供逻辑一致性的比较,例如,String 类重写 equals() 方法,所以可以用于两个不同对象,但是包含的字母相同的比较。
基本类型比较用,比较的是他们的值。默认下,对象用比较时,比较的是内存地址,如果需要比较对象内容,需要重写equal方法。
69、hashCode() 与 equals() 的相关规定
如果两个对象相等,则hashcode一定也是相同的。
两个对象相等,对两个对象分别调用equals方法都返回true。
两个对象有相同的hashcode值,它们也不一定是相等的。
hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)。
70、对象的相等与指向他们的引用相等,两者有什么不同
对象相等比的是内存中存放的内容是否相等
引用相等比较的是他们指向的内存地址是否相等
71、注解原理是什么
注解本质是一个继承了 Annotation 的特殊接口,其具体实现类是 Java 运行时生成的动态代理类。我们通过反射获取注解时,返回的是 Java 运行时生成的动态代理对象。通过代理对象调用自定义注解的方法,会最终调用 AnnotationInvocationHandler 的 invoke 方法,该方法会从 memberValues 这个 Map 中索引出对应的值,而 memberValues 的来源是 Java 常量池。
- 本文标题:面试题库 | Java基础知识
- 创建时间:2023-09-27 17:05:35
- 本文链接:2023/09/27/面试题库/面试题库 | Java基础知识/
- 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!