文章目录

  • 第一章 对象导论
  • 第二章 一切都是对象
  • 第三章 操作符
  • 第四章 控制执行流程
  • 第五章 初始化与清理
  • 第六章 访问权限控制
  • 第七章 复用类
  • 第八章 多态
  • 第九章 接口
  • 第十章 内部类
  • 第十一章 持有对象
  • 第十二章 通过异常处理错误
  • 第十三章 字符串
  • 第十四章 类型信息
  • 第十五章 泛型
  • 第十六章 数组
  • 第十七章 容器深入研究
  • 第十八章 Java I/O系统
  • 第十九章 枚举类型
  • 第二十章 注解
  • 第二十一章 并发
  • 第二十二章 图形化用户界面



第一章 对象导论

  1. Java对象是什么?
    对象具有状态、行为和标识(地址),每个对象都能提供服务,将问题分解为对象集合。
  2. Java类是什么?
    类描述了具有相同特性(成员变量)和行为(方法)的对象集合,一个类实际上就是一个数据类型。
  3. Java封装是什么?
    通过合并相同特性和行为来创建新的数据类型,也叫类。
  4. Java继承是什么?
    以现有的类为基础,复制它,然后通过增加和修改这个副本来创建新的类。一个基类型包含其所有导出类型所共享的特性和行为。
  5. Java多态是什么?
    面向对象程序采用了后期绑定的概念,程序直到运行时才能确定代码的地址,即当向对象发送消息时,被调用的代码直到运行时才能确定。
  6. Java动态内存分配方式是什么?
    java在堆内存池中动态地创建对象,直到运行到相关代码时才能确定需要创建多少对象、对象的生命周期、对象的具体类型,因此存储空间是在运行时动态管理的。
  7. Java单根集成结构的优点?
    所有的对象都具备了某些相同的行为;使垃圾回收更易实现。

第二章 一切都是对象

  1. 基本数据类型的所占字节数?
    byte、short、int、long、double、float、char、boolean;分别占用1、2、4、8、8、4、2、1个字节。
  2. 基本数据类型的所占字节数是否会变化?
    java基本数据类型所占存储空间大小的不变性是Java程序更具可移植性的原因之一。
  3. java基本数据类型初始化?
    java会确保基本数据类型的成员变量一定会被初始化,未主动赋值的会被赋予默认值。
  4. java存储数据的物理位置?
  1. 寄存器:最快的存储区,位于处理器内部,根据需求自动分配;
  2. 堆栈:位于RAM(随机访问内存),编译器需要明确知道堆栈内数据的生命周期;
  3. 堆:位于RAM(随机访问内存),存放所有的Java对象,编译器不需要知道堆内数据的生命周期;
  4. 常量存储:直接存放在代码内部;
  5. 非RAM存储:IO流、数据库。
  1. 方法的传参?
    基本数据类型传递值,引用数据类型传递对象的引用。
  2. 方法的唯一标识?
    方法名、参数列表合称为方法签名,用于唯一标识一个方法。
  3. static关键字的作用?
    static字段对每个类来说只占用一份存储空间,而非static字段对于每个对象来说都占用一份存储空间。
  4. javadoc的使用?
    javadoc只能为public和protected成员进行文档注释。
  5. java.lang包的通用性?
    java.lang包默认会被导入到每个java文件。

第三章 操作符

  1. 字符串如何与非字符串拼接?
    当编译器观察到字符串右边有一个“+”号,并且“+”号右边是一个非字符串,会尝试先把非字符串转换成String,再进行拼接。
  2. 小数类型的转换?
    将float和double转为整型时,默认是对其进行截尾。
  3. 位运算符?
  1. 与位符(&):两个输入位都是1才为1;
  2. 或位符(|):两个输入位有一个为1,就是1;
  3. 异或位符(^):两个输入位,一个为1,一个为0,才是1;
  4. 非位符(~):对单个输入位取反。
  1. 自动类型提升?
    byte、short、char在运算时会自动提升为int再进行运算,且计算结果也为int。不同类型的基本数据类型运算时,会自动提升至“较大”的类型。byte、short、char < int < long < float < double。

第四章 控制执行流程

  1. 臭名朝著的goto?
    合理地使用goto语句(带标签的break和continue)。

第五章 初始化与清理

  1. this关键字的作用?
    可以在构造器中使用this()调用另外一个构造器,但不能多次调用,且this()必须放在构造器的起始处,否则编译器报错。
  2. Just-In-time是什么?
    即时编译器可以将程序全部或者部分翻译成本地机器码。它有两种模式:
  1. 编译所有代码,耗时;
  2. 惰性评估:每次执行代码进行一小部分优化。
  1. 成员初始化的顺序?
    父类static成员变量 --> 父类static代码块 --> 子类static成员变量 --> 子类static代码块 --> 父类代码块 --> 父类构造函数 --> 子类代码块 --> 子类构造函数
  2. JVM执行垃圾回收的时机?
    如果虚拟机并未面临内存耗尽的情形,它是不会浪费时间去执行垃圾回收以恢复内存的,因此finalize()方法不可信。
  3. 垃圾回收时,如何处理对象引用的更新?
    位于静态存储区的引用会直接修改,而其它对象的引用,通过一次遍历后,将旧地址映射为新地址(记录在forward point头)。
  4. java如何分配空间?
    java用堆指针记录存储空间分配位置,比C++查找可用存储空间效率高,几乎可以与其他语言从堆栈分配空间的速度相媲美。
  5. 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
    }
}

结论:只把父类加载进了内存。

第六章 访问权限控制

  1. 编译单元是什么?
    一个.java源文件就一个编译单元,编译单元内最多只能有一个public类,且.java文件名必须与public类名相同。其他的非public类只能在当前编译单元内使用,且非public类为包访问权限(default)。如果一个编译单元内没有public类,那么.java源文件名字可任意取。
  2. packge、import关键字的作用?
    package和import共同用来解决名称空间冲突问题。package语句必须在编译单元内的第一行非注释代码。
  1. package:package access,表明当前编译单元是名为access类库的一部分;
  2. import:import access.A,表明导入access类库中的A编译单元
  1. 解释器加载.class文件的运行过程?
    首先找到环境变量CLASSPATH,然后获取包的名称并将“.”替换为反斜杠“\”,接着在这个目录下查找与要创建的类名称相同的.class文件。

第七章 复用类

  1. 名称屏蔽是什么?
    如果Java的基类拥有某个已经被多次重载的方法,在导出类中再次对该方法进行重载,并不会屏蔽(影响)基类的任何重载方法。
  2. final和private关键字?
    类中所有的private方法都会被隐式地指定为final方法,且private方法无法访问,自然也不能重写private方法。
  3. 重写对返回值和修饰符的限制?
    返回值类型,子类小于等于父类;权限修饰符类型,子类大于等于父类。

第八章 多态

  1. 方法的调用绑定?
    Java中除了static和final方法(private属于final)之外,其他所有的方法都是后期绑定。后期绑定的方法访问的都是声明类的域。
  2. 为什么要优先为基类完成初始化?
    只有基类构造器才有权限对自己的元素完成初始化,只有确保基类已完成初始化,才能确保子类对基类的修改操作是正常的。反之,若先完成子类初始化,可能会访问到尚未构建的父类元素。
  3. 手动销毁对象的注意事项?
    如果确实需要手动清理对象,销毁的顺序应与初始化的顺序相反。如:按成员变量声明相反的顺序销毁,优先销毁子类对象。

第九章 接口

  1. 使用接口的核心原因?
  1. java单继承多实现,使用接口可以向上转型为多种基类型;
  2. 防止客户端程序员直接创建基类型的对象,并确保这仅仅是为了声明一个接口。
  1. 通过继承来扩展接口,实现类需要实现所有的接口方法。
  2. 组合接口时,方法签名相同但返回值不同会造成编译报错。

第十章 内部类

  1. 内部类具有外围类所有元素的访问权。
  2. 内部类与外部类的联系?
    在拥有外部类对象前是不可能创建内部类对象的,内部类对象会隐式的关联到创建它的外部类对象上。如果是嵌套类(静态内部类),则不需要关联外部类的引用。
  3. 在内部类中如何访问外部类对象?
    OuterClass.this
  4. 如何创建内部类对象?
    Outer.Inner inner = new Outer().new Inner()。
  5. 普通内部类与嵌套类的区别?
  1. 普通内部类隐式保存了一份外部类的引用,通过外部类的对象来控制外部类特性和行为;嵌套类与外部类没有任何关系;
  2. 普通内部类不能含有static元素,而嵌套类一定是static类。
内部类有哪些?
  1. 普通内部类(public/protected/default/private都可) ;
  2. 局部内部类(不能被访问修饰符修饰);
  3. 匿名内部类(不能被访问修饰符修饰);
  4. 嵌套类(public/protected/default/private都可);
  5. 接口内部类(默认public static)。
  1. 局部内部类与匿名内部类比较?
  1. 匿名内部类只能创建一个实例;
  2. 局部内部类可以创建多个实例,且可以重载构造器。
  1. 为什么要使用内部类?
    解决“多重继承”,让多个内部类继承类,组合成一个拥有更多特性和行为的类。

第十一章 持有对象

第十二章 通过异常处理错误

  1. 异常处理的基本模型?
  1. 终止模型:一旦异常抛出,则将任务终止 ;
  2. 恢复模型:重新尝试调用出问题的方法。
  1. 异常声明throws的作用?
    提前告知客户端,某个方法可能会抛出的异常类型。
  2. 异常的分类?
    Throwable:任何可以作为异常被抛出的类;
    Error:编译时和系统错误;
    Exception:被抛出的异常的基本类型;
    RuntimeException:运行时异常,不受检查异常;
    CheckedException:不受检查异常,必须捕获或者作为异常声明抛出。
  3. 异常的缺陷?
    如果前一个异常尚未处理,就抛出下一个异常,可能导致上一个异常信息丢失。

第十三章 字符串

  1. 重载“+”?
    java重载操作符,“+”、“+=”在拼接字符串时被赋予了特殊的含义,这也算java仅有的两个重载操作符。
  2. 无意识的递归?
    在toString方法中拼接输出this,可能会导致递归。
  3. 字符串具有只读性。

第十四章 类型信息

  1. 面向对象编程的目录?
    让代码只操作对基类的引用,如果要新增一个派生类来扩展程序,就不会影响到原来的代码。
  2. 自动调用toString方法?
    如果某个对象出现在字符串表达式中(“+”、print),对象的toString方法就会被自动调用,以表示该对象的字符串形式。
  3. 基本数据类型的Class对象?
    int.class = Class = Integer.TYPE
  4. 新的类型转换语法?
    clazz.cast(obj) = (类型) obj 。
  5. 动态的instanceof?
    clazz.isInstance(obj)。

第十五章 泛型

  1. 泛型的局限性?
  1. 基本类型不能作为类型参数;
  2. 在泛型代码内部,无法获得任何有关泛型参数的信息。
  1. 泛型的分类?
    泛型类、泛型接口、泛型方法。
  2. 泛型通配符的分类?
  1. 上界通配符:<? super T>;
  2. 下界通配符:<? extends T>;
  3. 无界通配符:<?>。
  1. static方法无法访问泛型类的类型参数。因此,如果static方法需要使用泛型能力,就必须使其成为泛型static方法。
  2. 泛型方法与其所在的类是否是泛型类没有关系。
  3. 使用泛型类与泛型方法的区别?
    使用泛型类时,必须在创建对象的时候指定类型参数的值;使用泛型方法是,编译器会自动为泛型方法进行类型参数推断。
  4. Class.getTypeParameters()的作用?
    返回表示有泛型声明的类型参数的占位符,如T、V。
  5. 泛型类型参数将擦除到它的第一个边界。
  6. 泛型实现的原理?
    对传递进来的值进行编译时检查,对传递出去的值进行类型转换(虚拟机调用checkcast指令实现)。
  7. 不能对泛型参数给出一个超类型边界,即是错误的,但是可以<? super Mycalss>。
  8. 自限定类型:强制要求将正在定义的类作为类型参数传递给基类。如:<T extends Animal>。
  9. 如何创建泛型数组?
public <T> T[] create(Class<T> clazz,int size){
	return (T[]) Array.newInstance(clazz, size);
}
  1. 为什么泛型用擦除实现?
    在jdk5前,是不存在泛型的,使用擦除实现,是为了解决移植兼容性问题,允许泛化代码与非泛化的代码共存。

第十六章 数组

  1. 不能创建泛型数组。
  2. 数组与容器比较?
    数组的性能优于容器,但是容器更灵活。

第十七章 容器深入研究

  1. Comparable的注意事项?
    在实现Comparable接口并重写compareTo方法时,不要返回a - b ,一旦b是个负数,有可能会导致返回值溢出Integer.Max_VALUE,建议使用三元表达式,返回 1或-1。

第十八章 Java I/O系统

  1. RandomAccessFile,既支持读又支持读写。
  2. 字节存放次序?
    不同的机器可能会以不同的字节排序存储数据。高位优先:优先把字节数据存在在右边存储单元;低位优先:优先把字节数据存储在左边存储单元。可以通过ByteBuffer.order控制。
  3. NIO是什么?
    NIO通过通道(Channel)和换缓冲器(Buffer)来提高IO速度,NIO修改了旧IO类库的FileInputStream、FileOutputStream、RandomAccessFile用于产生FileChannel。
  4. ByteBuffer是什么?
    ByteBuffer是最基本的缓冲器,其它的缓冲器都称为视图缓冲器(可以通过某种基本数据类型的视窗查看底层的ByteBuffer)。
  5. 内存映射文件的作用?
    内存映射文件(MappedByteBuffer)允许我们创建和修改那些因为太大而不能放入内存的文件。
  6. 文件加锁?
    FileLock依赖于底层操作系统实现,如果锁已经被操作系统获取,java程序也会无法获取锁。
  1. FileChannel.tryLock:尝试获取锁,如果失败则直接return;
  2. FileChannel.lock:阻塞式获取锁。
  3. FileChannel.lock ( potition , size , shared ):文件部分加锁。
  1. 不调用构造函数创建对象?
    在对一个Serializable对象还原的过程中,是不调用任何构造函数的。
  2. 序列化控制?
  1. 实现Externalizable接口,重写writeExternal和readExternal方法;
  2. 实现Serializable接口,添加readObject和writeObject方法如下:
private void writeObject(java.io.ObjectOutputStream out)
  throws IOException
 private void readObject(java.io.ObjectInputStream in)
  throws IOException, ClassNotFoundException;
  1. transient和static字段都不会被序列化。
  1. 序列化的其它方式?
    XML、Preferences。

第十九章 枚举类型

  1. 枚举的实现?
    创建enum时,编译器会自动为这个enum生成一个相关的类,这个类继承java.lang.Enum。
  2. 枚举实例的创建?
    枚举实例可以用 == 来比较,枚举实例必须声明在第一行,且用分号结尾。
  3. myEnum.values方法?
    values方法是由编译器自动插入到枚举定义中的static方法,并不是继承自Enum类。
  4. EnumSet和EnumMap的输出顺序取决于enum实例定义的顺序。

第二十章 注解

  1. 注解元素可用的类型如下:
    基本数据类型、String、Class、enum、Annotation、以上类型的数组。
  2. 注解元素默认值限制?
    注解元素必须有值,即注解元素要么有默认值,要么必须在使用时提供值。

第二十一章 并发

  1. 守护线程(后台线程)是什么?
    后台线程是指程序运行时提供的一种通用服务线程,这种线程并不属于程序不可或缺的一部分。因此,当所有的非后台线程结束时,程序也就结束了,同时会杀死进程中的所有后台线程。
  2. 如何设置守护线程?
    在线程启动前调用Thread.setDaemon方法,守护线程创建的线程默认也是守护线程。
  3. JVM字撕裂?
    JVM会将64位(long、double变量)的读写操作分离成两个32位操作来执行,如果在读写期间,发生上下文切换,可能会看到部分被修改过的数值,可以通过volatile关键字解决。
  4. 产生死锁的条件?
  1. 互斥条件;
  2. 请求与保持条件;
  3. 不可剥夺条件;
  4. 循环等待条件。
  1. 线程优先级priority?
    调用Thread.setPriority方法设置线程的优先级,优先级高的线程获得CPU执行权的概率大,但不是一定能获得,且优先级依赖于特定的平台,不建议手动设置优先级。

第二十二章 图形化用户界面