文章目录
- 第一章 对象导论
- 第二章 一切都是对象
- 第三章 操作符
- 第四章 控制执行流程
- 第五章 初始化与清理
- 第六章 访问权限控制
- 第七章 复用类
- 第八章 多态
- 第九章 接口
- 第十章 内部类
- 第十一章 持有对象
- 第十二章 通过异常处理错误
- 第十三章 字符串
- 第十四章 类型信息
- 第十五章 泛型
- 第十六章 数组
- 第十七章 容器深入研究
- 第十八章 Java I/O系统
- 第十九章 枚举类型
- 第二十章 注解
- 第二十一章 并发
- 第二十二章 图形化用户界面
第一章 对象导论
- Java对象是什么?
对象具有状态、行为和标识(地址),每个对象都能提供服务,将问题分解为对象集合。 - Java类是什么?
类描述了具有相同特性(成员变量)和行为(方法)的对象集合,一个类实际上就是一个数据类型。 - Java封装是什么?
通过合并相同特性和行为来创建新的数据类型,也叫类。 - Java继承是什么?
以现有的类为基础,复制它,然后通过增加和修改这个副本来创建新的类。一个基类型包含其所有导出类型所共享的特性和行为。 - Java多态是什么?
面向对象程序采用了后期绑定的概念,程序直到运行时才能确定代码的地址,即当向对象发送消息时,被调用的代码直到运行时才能确定。 - Java动态内存分配方式是什么?
java在堆内存池中动态地创建对象,直到运行到相关代码时才能确定需要创建多少对象、对象的生命周期、对象的具体类型,因此存储空间是在运行时动态管理的。 - Java单根集成结构的优点?
所有的对象都具备了某些相同的行为;使垃圾回收更易实现。
第二章 一切都是对象
- 基本数据类型的所占字节数?
byte、short、int、long、double、float、char、boolean;分别占用1、2、4、8、8、4、2、1个字节。 - 基本数据类型的所占字节数是否会变化?
java基本数据类型所占存储空间大小的不变性是Java程序更具可移植性的原因之一。 - java基本数据类型初始化?
java会确保基本数据类型的成员变量一定会被初始化,未主动赋值的会被赋予默认值。 - java存储数据的物理位置?
- 寄存器:最快的存储区,位于处理器内部,根据需求自动分配;
- 堆栈:位于RAM(随机访问内存),编译器需要明确知道堆栈内数据的生命周期;
- 堆:位于RAM(随机访问内存),存放所有的Java对象,编译器不需要知道堆内数据的生命周期;
- 常量存储:直接存放在代码内部;
- 非RAM存储:IO流、数据库。
- 方法的传参?
基本数据类型传递值,引用数据类型传递对象的引用。 - 方法的唯一标识?
方法名、参数列表合称为方法签名,用于唯一标识一个方法。 - static关键字的作用?
static字段对每个类来说只占用一份存储空间,而非static字段对于每个对象来说都占用一份存储空间。 - javadoc的使用?
javadoc只能为public和protected成员进行文档注释。 - java.lang包的通用性?
java.lang包默认会被导入到每个java文件。
第三章 操作符
- 字符串如何与非字符串拼接?
当编译器观察到字符串右边有一个“+”号,并且“+”号右边是一个非字符串,会尝试先把非字符串转换成String,再进行拼接。 - 小数类型的转换?
将float和double转为整型时,默认是对其进行截尾。 - 位运算符?
- 与位符(&):两个输入位都是1才为1;
- 或位符(|):两个输入位有一个为1,就是1;
- 异或位符(^):两个输入位,一个为1,一个为0,才是1;
- 非位符(~):对单个输入位取反。
- 自动类型提升?
byte、short、char在运算时会自动提升为int再进行运算,且计算结果也为int。不同类型的基本数据类型运算时,会自动提升至“较大”的类型。byte、short、char < int < long < float < double。
第四章 控制执行流程
- 臭名朝著的goto?
合理地使用goto语句(带标签的break和continue)。
第五章 初始化与清理
- this关键字的作用?
可以在构造器中使用this()调用另外一个构造器,但不能多次调用,且this()必须放在构造器的起始处,否则编译器报错。 - Just-In-time是什么?
即时编译器可以将程序全部或者部分翻译成本地机器码。它有两种模式:
- 编译所有代码,耗时;
- 惰性评估:每次执行代码进行一小部分优化。
- 成员初始化的顺序?
父类static成员变量 --> 父类static代码块 --> 子类static成员变量 --> 子类static代码块 --> 父类代码块 --> 父类构造函数 --> 子类代码块 --> 子类构造函数 - JVM执行垃圾回收的时机?
如果虚拟机并未面临内存耗尽的情形,它是不会浪费时间去执行垃圾回收以恢复内存的,因此finalize()方法不可信。 - 垃圾回收时,如何处理对象引用的更新?
位于静态存储区的引用会直接修改,而其它对象的引用,通过一次遍历后,将旧地址映射为新地址(记录在forward point头)。 - java如何分配空间?
java用堆指针记录存储空间分配位置,比C++查找可用存储空间效率高,几乎可以与其他语言从堆栈分配空间的速度相媲美。 - JVM将.class文件加载进内存的时机?
当首次调用构造函数、静态方法、静态域时,会触发类的最小范围初始化,将.class文件加载进内存。
public class Father {
static int a = 1;
static {
System.out.println("father");
}
}
public class Son extends Father{
static {
System.out.println("son");
}
}
public class Main {
public static void main(String[] args) {
System.out.println(Son.a); // father // 1
}
}
结论:只把父类加载进了内存。
第六章 访问权限控制
- 编译单元是什么?
一个.java源文件就一个编译单元,编译单元内最多只能有一个public类,且.java文件名必须与public类名相同。其他的非public类只能在当前编译单元内使用,且非public类为包访问权限(default)。如果一个编译单元内没有public类,那么.java源文件名字可任意取。 - packge、import关键字的作用?
package和import共同用来解决名称空间冲突问题。package语句必须在编译单元内的第一行非注释代码。
- package:package access,表明当前编译单元是名为access类库的一部分;
- import:import access.A,表明导入access类库中的A编译单元
- 解释器加载.class文件的运行过程?
首先找到环境变量CLASSPATH,然后获取包的名称并将“.”替换为反斜杠“\”,接着在这个目录下查找与要创建的类名称相同的.class文件。
第七章 复用类
- 名称屏蔽是什么?
如果Java的基类拥有某个已经被多次重载的方法,在导出类中再次对该方法进行重载,并不会屏蔽(影响)基类的任何重载方法。 - final和private关键字?
类中所有的private方法都会被隐式地指定为final方法,且private方法无法访问,自然也不能重写private方法。 - 重写对返回值和修饰符的限制?
返回值类型,子类小于等于父类;权限修饰符类型,子类大于等于父类。
第八章 多态
- 方法的调用绑定?
Java中除了static和final方法(private属于final)之外,其他所有的方法都是后期绑定。后期绑定的方法访问的都是声明类的域。 - 为什么要优先为基类完成初始化?
只有基类构造器才有权限对自己的元素完成初始化,只有确保基类已完成初始化,才能确保子类对基类的修改操作是正常的。反之,若先完成子类初始化,可能会访问到尚未构建的父类元素。 - 手动销毁对象的注意事项?
如果确实需要手动清理对象,销毁的顺序应与初始化的顺序相反。如:按成员变量声明相反的顺序销毁,优先销毁子类对象。
第九章 接口
- 使用接口的核心原因?
- java单继承多实现,使用接口可以向上转型为多种基类型;
- 防止客户端程序员直接创建基类型的对象,并确保这仅仅是为了声明一个接口。
- 通过继承来扩展接口,实现类需要实现所有的接口方法。
- 组合接口时,方法签名相同但返回值不同会造成编译报错。
第十章 内部类
- 内部类具有外围类所有元素的访问权。
- 内部类与外部类的联系?
在拥有外部类对象前是不可能创建内部类对象的,内部类对象会隐式的关联到创建它的外部类对象上。如果是嵌套类(静态内部类),则不需要关联外部类的引用。 - 在内部类中如何访问外部类对象?
OuterClass.this - 如何创建内部类对象?
Outer.Inner inner = new Outer().new Inner()。 - 普通内部类与嵌套类的区别?
- 普通内部类隐式保存了一份外部类的引用,通过外部类的对象来控制外部类特性和行为;嵌套类与外部类没有任何关系;
- 普通内部类不能含有static元素,而嵌套类一定是static类。
内部类有哪些?
- 普通内部类(public/protected/default/private都可) ;
- 局部内部类(不能被访问修饰符修饰);
- 匿名内部类(不能被访问修饰符修饰);
- 嵌套类(public/protected/default/private都可);
- 接口内部类(默认public static)。
- 局部内部类与匿名内部类比较?
- 匿名内部类只能创建一个实例;
- 局部内部类可以创建多个实例,且可以重载构造器。
- 为什么要使用内部类?
解决“多重继承”,让多个内部类继承类,组合成一个拥有更多特性和行为的类。
第十一章 持有对象
第十二章 通过异常处理错误
- 异常处理的基本模型?
- 终止模型:一旦异常抛出,则将任务终止 ;
- 恢复模型:重新尝试调用出问题的方法。
- 异常声明throws的作用?
提前告知客户端,某个方法可能会抛出的异常类型。 - 异常的分类?
Throwable:任何可以作为异常被抛出的类;
Error:编译时和系统错误;
Exception:被抛出的异常的基本类型;
RuntimeException:运行时异常,不受检查异常;
CheckedException:不受检查异常,必须捕获或者作为异常声明抛出。 - 异常的缺陷?
如果前一个异常尚未处理,就抛出下一个异常,可能导致上一个异常信息丢失。
第十三章 字符串
- 重载“+”?
java重载操作符,“+”、“+=”在拼接字符串时被赋予了特殊的含义,这也算java仅有的两个重载操作符。 - 无意识的递归?
在toString方法中拼接输出this,可能会导致递归。 - 字符串具有只读性。
第十四章 类型信息
- 面向对象编程的目录?
让代码只操作对基类的引用,如果要新增一个派生类来扩展程序,就不会影响到原来的代码。 - 自动调用toString方法?
如果某个对象出现在字符串表达式中(“+”、print),对象的toString方法就会被自动调用,以表示该对象的字符串形式。 - 基本数据类型的Class对象?
int.class = Class = Integer.TYPE - 新的类型转换语法?
clazz.cast(obj) = (类型) obj 。 - 动态的instanceof?
clazz.isInstance(obj)。
第十五章 泛型
- 泛型的局限性?
- 基本类型不能作为类型参数;
- 在泛型代码内部,无法获得任何有关泛型参数的信息。
- 泛型的分类?
泛型类、泛型接口、泛型方法。 - 泛型通配符的分类?
- 上界通配符:<? super T>;
- 下界通配符:<? extends T>;
- 无界通配符:<?>。
- static方法无法访问泛型类的类型参数。因此,如果static方法需要使用泛型能力,就必须使其成为泛型static方法。
- 泛型方法与其所在的类是否是泛型类没有关系。
- 使用泛型类与泛型方法的区别?
使用泛型类时,必须在创建对象的时候指定类型参数的值;使用泛型方法是,编译器会自动为泛型方法进行类型参数推断。 - Class.getTypeParameters()的作用?
返回表示有泛型声明的类型参数的占位符,如T、V。 - 泛型类型参数将擦除到它的第一个边界。
- 泛型实现的原理?
对传递进来的值进行编译时检查,对传递出去的值进行类型转换(虚拟机调用checkcast指令实现)。 - 不能对泛型参数给出一个超类型边界,即是错误的,但是可以<? super Mycalss>。
- 自限定类型:强制要求将正在定义的类作为类型参数传递给基类。如:<T extends Animal>。
- 如何创建泛型数组?
public <T> T[] create(Class<T> clazz,int size){
return (T[]) Array.newInstance(clazz, size);
}
- 为什么泛型用擦除实现?
在jdk5前,是不存在泛型的,使用擦除实现,是为了解决移植兼容性问题,允许泛化代码与非泛化的代码共存。
第十六章 数组
- 不能创建泛型数组。
- 数组与容器比较?
数组的性能优于容器,但是容器更灵活。
第十七章 容器深入研究
- Comparable的注意事项?
在实现Comparable接口并重写compareTo方法时,不要返回a - b ,一旦b是个负数,有可能会导致返回值溢出Integer.Max_VALUE,建议使用三元表达式,返回 1或-1。
第十八章 Java I/O系统
- RandomAccessFile,既支持读又支持读写。
- 字节存放次序?
不同的机器可能会以不同的字节排序存储数据。高位优先:优先把字节数据存在在右边存储单元;低位优先:优先把字节数据存储在左边存储单元。可以通过ByteBuffer.order控制。 - NIO是什么?
NIO通过通道(Channel)和换缓冲器(Buffer)来提高IO速度,NIO修改了旧IO类库的FileInputStream、FileOutputStream、RandomAccessFile用于产生FileChannel。 - ByteBuffer是什么?
ByteBuffer是最基本的缓冲器,其它的缓冲器都称为视图缓冲器(可以通过某种基本数据类型的视窗查看底层的ByteBuffer)。 - 内存映射文件的作用?
内存映射文件(MappedByteBuffer)允许我们创建和修改那些因为太大而不能放入内存的文件。 - 文件加锁?
FileLock依赖于底层操作系统实现,如果锁已经被操作系统获取,java程序也会无法获取锁。
- FileChannel.tryLock:尝试获取锁,如果失败则直接return;
- FileChannel.lock:阻塞式获取锁。
- FileChannel.lock ( potition , size , shared ):文件部分加锁。
- 不调用构造函数创建对象?
在对一个Serializable对象还原的过程中,是不调用任何构造函数的。 - 序列化控制?
- 实现Externalizable接口,重写writeExternal和readExternal方法;
- 实现Serializable接口,添加readObject和writeObject方法如下:
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
- transient和static字段都不会被序列化。
- 序列化的其它方式?
XML、Preferences。
第十九章 枚举类型
- 枚举的实现?
创建enum时,编译器会自动为这个enum生成一个相关的类,这个类继承java.lang.Enum。 - 枚举实例的创建?
枚举实例可以用 == 来比较,枚举实例必须声明在第一行,且用分号结尾。 - myEnum.values方法?
values方法是由编译器自动插入到枚举定义中的static方法,并不是继承自Enum类。 - EnumSet和EnumMap的输出顺序取决于enum实例定义的顺序。
第二十章 注解
- 注解元素可用的类型如下:
基本数据类型、String、Class、enum、Annotation、以上类型的数组。 - 注解元素默认值限制?
注解元素必须有值,即注解元素要么有默认值,要么必须在使用时提供值。
第二十一章 并发
- 守护线程(后台线程)是什么?
后台线程是指程序运行时提供的一种通用服务线程,这种线程并不属于程序不可或缺的一部分。因此,当所有的非后台线程结束时,程序也就结束了,同时会杀死进程中的所有后台线程。 - 如何设置守护线程?
在线程启动前调用Thread.setDaemon方法,守护线程创建的线程默认也是守护线程。 - JVM字撕裂?
JVM会将64位(long、double变量)的读写操作分离成两个32位操作来执行,如果在读写期间,发生上下文切换,可能会看到部分被修改过的数值,可以通过volatile关键字解决。 - 产生死锁的条件?
- 互斥条件;
- 请求与保持条件;
- 不可剥夺条件;
- 循环等待条件。
- 线程优先级priority?
调用Thread.setPriority方法设置线程的优先级,优先级高的线程获得CPU执行权的概率大,但不是一定能获得,且优先级依赖于特定的平台,不建议手动设置优先级。
第二十二章 图形化用户界面