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的多态表现在哪里
多态要有动态绑定,否则就不是多态,