Java核心面试题必备 *

1.1面向对象的三个基本特征

继承:

        让某个类型的对象获得另一个类型的对象的属性和方法。继承就是子类继承父类的特征和行为,使得子类对象具有父类的实例域和方法,或子类从谷类继承发方法,使得子类具有父类相同的行为。

封装:

        隐藏部分对象的属性和实现细节,对数据的访问只能通过对外公开的接口。通过这种方式,对象内部数据提供了不同级别的保护,以防止程序无关的部分意外改变或错误的使用了对象的私有部分。

多态:

        对于同一个行为,不同的子类对象具有不同的表现形式。多态存在的三个条件:

        1.1.1)继承

        1.1.2)重写

        1.1.3)父类的引用指向子类对象

举一个简单的例子:

        lol里边对于不同英雄人物都拥有Q 技能,但是 每个人物的Q 技能都是不一样的。

1.2访问修饰符 public 、private 、protect以及不写(default) 时的区别?

修饰符当前类同包子类其它包
public
protected√        ×
default××
private×××

类的成员不写访问修饰符默认为default,默认对于同一个包的其它类相当于公开public,对于不是同一个包的其它类相当于私有。

受保护protected对子类相当于公开,对于不是同一个包没有父子类关系的相当于私有

Java中,外部类的修饰符只能时public或默认,类的成员 包括内部类的修饰符可以是以上四种。

1.3、下面两个代码块能正常编译和执行吗?

//代码块一
short i = 1;
short i2 = i + 1;

//代码块二
short i = 1;
short i2 += 1;

代码块一,编译出错,int类型转换成short类型会出现损失

代码块二,正常编译和执行,编译后相当于 short i2 = short(i + 1)

1.4、基础考察,指出下题的输出结果?

public static void main(String[] args) {
    Integer a = 128, b = 128, c = 127, d = 127;
    System.out.println(a == b);
    System.out.println(c == d);
}

答案: false , true

自动装箱:

        Integer包装类的范围; -128 ~ 127,大于这个范围就出了缓存范围,就会重新创建

1.5、用最有效率的方法计算2*8

2<<3

(左移,相当于乘以 2 的几次幂 n << m 相当于n*2的m次幂)

进阶:

        通常情况下,可以认为运算时性能最高的。但是,其实编译器仙子啊已经非常聪明了,很多指令编译器都可以自己做优化,所以在实际中,我们不需要特意去追求使用位运算,这样不仅会导致代码可读性很差,而且还可能会影响编译器自主的优化功能。

1.6& 和 && 的区别

&&: 逻辑与运算符。当运算符左右两边的表达式都为true ,才返回true。同时具有短路性,如果第一个表达式为false ,则直接返回false。

&: 逻辑与运算符,按位运算符。

只有当两个都为true 才为 true ,否则就是false,并且它不具有短路性

1.7String 是Java基本数据类型吗?

不是,Java中的基本上数据类型有八个,byte 、short、int、long、double、float、char、boolean;除了基本数据类型外,剩下的都是引用数据类型。

基本数据类型:数据直接存储在栈上

引用数据类型区别:数据存储在堆上,栈上只存储引用地址。

1.8String 类可以继承吗?

不可以,String 类使用final修饰,不能被继承。

1.9、String 和 StringBuilder 、 StringBuffer的区别?

String: String的值被创建之后不能被修改,对任何String的修改都会引发新的String对象的生成。

StringBuffer:和String 类似,但是值可以被修改,使用sychronzied 来保证线程安全。

StringBuilder:StringBuffer的非线程安全版本,没有使用sychronized ,具有更高的性能,推荐优先使用。

1.10、String s = new String("xyz")创建了几个字符串对象?

一个或两个;

如果字符串常量池有"xyz",则是一个,否则是两个;

当字符串常量池中没有"xyz",此时会创建下边两个对象:

        一个是字符串字面量"xyz"所对应的、驻留在一个全局共享的字符串常量池中的实例,此时该实例也是在堆中,字符串常量池中放引用。

        另一个是通过new String()创建并初始化的,内容与"xyz"相同的实例,也是在堆中。

1.11、String s = “xyz”和String s = new String ("xyz") 区别?

两个语句都会先去字符串常量池中检查是否已经存在"xyz",如果有则直接使用,如果没有则会在常量池中创建"xyz"对象。

另外,String s = new String("xyz"),还会通过new String()在堆里面创建一个内容与"xyz"相同或的对象实例。

所以前者其实理解为被后者所包含。

1.12、== 和equals的区别是什么?

==:运算符,用于比较基本类型变量和引用类型变量。

对于基本类型变量,比较的变量保存的值是否相同,类型不一定要相同。

对于引用数据类型的变量,比较的是两个对象的地址值是否相同。

equals:Object 类中定义的方法,通常用于比较两个对象的值是否相等。

equals 在object方法中其实等于 == ,但是在实际应用中,equals 通常被重写用于比较两个对象的值是否相同。

1.13、两个对象的hashCode()相同,则equals()也一定为true,对吗?

不对,

        当a.equals(b) = true 时,则a.hashCode == b.hashCode() 必然成立,反过来不一定成立。

1.14、什么是反射?

反射是指在运行状态中,对于任意一个类都能够直到这个类所有的属性和方法;并且对于任意一个对象,都能够调用它的任意一个方法;这种动态获取信息以及动态调用对象方法的功能称为反射机制。

反射涉及到四个核心类:

        类对象: Class.Java

        类的构造器对象:Constructor.Java

        类的方法对象:Method.Java

        类的属性对象:Field.java

反射有什么用?

        操作因访问权限限制的属性和方法

        实现自定义注解

        动态加载第三方jar包

        按需加载类,节省编译和吃实话APk的时间

反射的工作原理:

        当我们编写完一个Java项目之后,每一个Java文件都会被编译成一个.class文件,这些Class对象承载了这个类的所有信息,包括父类、接口、构造函数、方法、属性等,这些class文件在程序运行时会被ClassLoader架子啊到虚拟机中。当一个类被加载以后 Java虚拟机就会在内存中自动产生一个class 对象,我们通过new的形式创建对象实际上就是通过这些class来创建,只是这个过程对于我们是不透明的而已。

反射的工作原理就是借助Class.java、Consrtuctor.Java、Method.Java、Field.Java  这四个类在程序运行时动态访问和修改任何类的行为及状态。

1.15、深度拷贝和浅拷贝的去呗是什么?

数据分为基本数据类型和引用数据类型。

基本数据类型:数据直接存储在栈中

引用数据类型:存储在栈中的是随想的引用的地址,真实的对象数据存放在堆内存中。

浅拷贝:

        对于基本数据类型:直接复制数据;

        对于引用数据类型:只是复制了对象的引用地址,新旧对象指向同一个内存的地址,修改其中一个对象的指,另一个对象的值随之改变。

深拷贝:

        对于基本数据类型:直接复制数据值

        对于引用数据类型:开辟新的内存空间,在新的内存空间里复制一个一模一样的对象,新老对象不共享内存,修改其中一个对象的值,不会影响另一个对象。

深拷贝相比于浅拷贝速度较慢并且花销比较大。

1.16、并发和并行有什么区别?

并发:两个 或多个事件在同一时间间隔发生。

并行:两个或多个事件在同一时刻发生。

并行是真正意义上,同一时刻做多件事情,而并发在同一时刻只会做一件事情,并发能够在单处理器系统中存在是因为并发是并行的假象,并行要求程序能够同时执行多个操作,而并发只是要求程序假装同时执行多个操作(每个小时片执行一个操作,多个操作快速切换执行)。

当系统有一个以上cpu时,则线程的操作有可能非并发。当一个cpu执行一个线程时,另一个cpu可以执行另一个线程,两个线程互补抢占cpu资源,可以同时进行,这种方式我们称之为并行。

并发编程的目标是充分的利用处理器的每一个核,以达到最高的处理器性能。

1.17、当一个对象被当作参数传递到一个方法后,此方法可以改变这个对象的属性,并可返回变化后的结果,那么这里到底是传递至还是引用传递?

值传递,Java中只有值传递,对于对象参数,值得内容是对象的引用。

1.18、重载(Overload)和重写(Override)的区别?

方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。

重载:一个类中有多个同名的方法,但是具有有不同参数列表(参数类型不同,参数个数不同,或者二者都不相同)。

重写:发生在子类和父类之间,子了对父类的方法进行重写,参数都不能改变,返回值类型可以不相同,但是必须是父类返回值的派生类。及外壳不变,核心重写!重写的好处在于子类可以根据需要,定义特定于自己的行为。

1.19、构造器是否可以被重写?

构造器不能被重写,但是可以被重载,所以你可以看到一个类中有多个构造函数的情况。

1.20、为什么不能根据返回类型来区分重载?

如果我们有两个方法如下:当我们调用test(1)时,编译器无法确认调用的是哪一个。

//方法一
int test(int i);
//方法二
long test(long l);

方法的返回值只是作为方法运行之后的一个状态,但是并不是所有调用都关注返回值,所以不能将返回值作为重载的唯一区分条件。

1.21、Java静态变量和成员变量的区别

 成员变量存在于堆内存中。静态变量存在于方法区中。

成员变量于对象共存亡,随着对象的创建而存在,随着对象被回收而释放。静态变量与类共存亡,随着类的加载而存在,随着类的消失而消失。

成员变量所属于对象,所以也称为实例变量。静态变量所属于类,所以也称为类变量。

成员变量只能被对象所调用。静态变量可以被对象调用,也可以被类名调用。

1.22、是否可以从一个静态方法内部发出对非静态方法的调用?

区分两种情况:发出调用时是否显示创建了对象实例。

1)没有显示创建对象实例:不可以发起调用,非静态方法只能被对象调用,静态方法可以通过对象调用,也可以通过类调用,所以静态方法被调用时,可能还没有创建任何实例对象。因此通过静态方法内部发出对非静态方法的调用,此时肯能无法知道非静态方法属于那个对象。

静态方法内部直接调用非静态方法,编译直接报错

2)显示创建对象实例:可以发起调用,在静态方法中显示的创建对象实例,则可以正常调用。

先创建对象,在调用非静态方法:成功执行 可以

1.23、初始化考察,请指出下面程序运行的结果。

执行结果:ABabab

1)静态变量只会初始化一次

2)当有父类时,完整的初始化顺序为:父类经他变量(静态代码块)- 》子类静态变量(静态代码块) - 》父类非静态变量(非静态代码块) - 》父类构造器 - 》子类非静态变量(非静态代码块)-  》子类构造器。

1.24、抽象类 和 接口有什么区别?

1)抽象类只能单继承,接口可以多实现

2)抽象类可以有构造方法,接口中不能有构造方法。

3)抽象类中可以有成员变量,接口中没有成员变量,只能有常量

4)抽象类中可以包含非抽象的方法,在Java7之前接口中的所有方法都是抽象的,在Java8之后,接口支持非抽象方法:default方法、静态方法。Java9支持有方法、私有静态方法。

5)抽象类中抽象方法类型可以是任意修饰符,Java8之前接口中的方法只能是public 类型,Java9 支持private类型。

设计思想的区别:

接口是自上而下的抽象过程,接口规范了某些行为,是对某一行为的抽象。我需要这个行为,我就去实现某个接口,但是具体这个行为怎么实现,完全由自己决定。

抽象类是自下而上的抽象过程,抽象类提供了通用实现,是对某一类事务的抽象。我们在写实现类的时候,发现某些实现类具有几乎相同的实现,因此我们将这些相同的实现抽取出来称为抽象类,然后如果有一些差异点,则可提供抽象方法来支持自定义实现。

网上的形象说法:

        普通类就是亲爹:它有啥都给你

        抽象类像叔伯:给你一部分,还可以知道你做事的方法

        接口像干爹:可以给你指引方法,具体做成什么还得是你自己努力实现

1.25、Java中的final关键字有那些用法?

修饰类:该类不能再派生出新的子类,不能作为父类继承。因此一个类不能同时被声明为abstract 和 final。

修饰方法:该方法不能被子类重写。

修饰变量:该变量必须在声明时定初始值,而在以后只能读取,不可修改,如果变量是对象,则指的是引用不可修改,但是对象的属性还是可以修改的。

1.26、阐述final、finally、finalize的区别

三者是完全不相关的东西,只是名字有点像。

final如上:

finally:finally 是对Java异常处理机制的最佳补充,通常配合try catch 使用,用于存放那些无论是否出现异常都一定会执行的代码。在实际使用中,通常用于释放锁,数据库连接等资源,把资源释放方法到finally中,可以大大降低程序出错的机率。

finalize:Object的方法,在垃圾回收器将对象从内存中清除出去之前做的必要的清理工作。

finalize:方法仅做为了解即可,在Java9中该方法已经被标记为废弃,添加了新的方法cleaner。

1.27、try、catch、finnally考察,请指出下面程序运行的结果。

 执行结果:31

在程序结束之前执行finally的方法。

1.28、try、catch、finnally考察,请指出下面程序运行的结果。(2)

 

执行结果:3 

在执行finally的方法时程序直接结束。

1.29、try、catch、finally 考察3,请指出下⾯程序的运⾏结果(3)

执行结果:2

在执行finally之前,jvm会先将i的结果暂存起来,然后finally执行完毕后,会返回之前暂存的结果,而不是返回 i 。

 1.30、Error 和 exception 有什么区别?

这两者都是Throwable 的子类,用于表示程序出现不正常的情况。

Error :表示系统级的错误和程序不必处理的异常,是恢复不是不可能但是很困难的情况下的一种严重问题,比如内存溢出,不可能指望程序处理这样的情况。

Exception:表示需要捕捉或者需要程序进行处理的异常,是一种设计实现问题,也就是说,它表示如果程序运行正常,从不会发生的情况。

1.31、JDK1.8之后有哪些新特性

1)接口默认方法:Java8之后允许我们给接口添加一个非抽象的方法实现,之许哟啊使用default关键字即可。

从Java8开始,引入了接口默认方法,这样的好处也是很明显的,首先解决了Java8以前版本接口兼容性问题i,同时对于我们以后的程序开发,也可以在接口子类中直接使用接口的默认方法,而不再需要在各个子类中各自实现相应接口的方法。

2)Lambda表达式和函数式接口:lambda 表达式本质上是一段匿名内部类,也可以是一段可以传递的代码, lambda允许吧函数作为一个方法的参数(函数作为参数传递到方法中) , 使用lambda Bloch 建议使用lambda表达式最好不要超过三行

函数式接口

lambda表达式需要函数式接口的支持,所以我们有必要来说说什么式函数式接口。

直播啊汗一个抽象方法的接口,称为函数式接口。可以通过lambda表达式来创建该接口对象。

3)Steam Api :用函数式编程方式在集合类上进行复杂操作的工具,配合lambda 表达式可以方便的对集合进行处理。Java8中处理集合的关键抽象概念,它可以指定你希望对集合进行操作,就类似于使用sql 执行的数据库查询。也可以使用Steam API 来并行执行操作。简而言之,Steam API提供了一种高效且易于使用的处理数据的方式。

4)方法的引用:方法引用提供了非常有用的语法,可以直接引用已有Java类对象,的方法或构造器。与lambda联合使用,方法引用可以使得语言的否早更紧凑简洁。减少溶于代码。

方法引用就是操作符::将方法名和对象或类的名i在分隔开来

5)日期时间API:Java8引入了新的日期时间API改进了日期时间的夫案例。在Java8之气那,所有关于时间日期的API都存在股份中使用方面的缺陷。

1.32、Java的多态表现在哪里

多态要有动态绑定,否则就不是多态,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值