0、问题大纲
一、Java 基础
1.1 Java概念原理
1、谈谈你对Java平台的理解?【第1讲】
- 追问1:面向过程和面向对象有什么区别?
- 追问2:Java中为什么要写None Static Method(非静态方法/实例化方法)?
- 追问3:Java和Python的区别
- 追问4:Java 高级特性?
- 追问5:“Java 是解释执行”,这个说法正确吗?
2、动态代理是基于什么原理?【第6讲】(运行时自省,获取类声明属性和方法)
3、Java为什么不能多继承?
- 追问1:如何实现多继承?
4、谈谈接口和抽象类有什么区别?【第13讲】(*3)
5、什么是内部类,什么是匿名内部类?
6、重写和重载的区别。(*2)
- 追问1:多态含义?
7、Exception和Error有什么区别?【第2讲】:Throwable类;可预料VS不可恢复;可检查+不可检查
- 追问1:你了解哪些 Error、Exception 或者 RuntimeException?
- 追问2:NoClassDefFoundError 和 ClassNotFoundException 有什么区别?
- 追问3:异常处理有哪些原则?
8、谈谈final、finally、 finalize有什么不同?【第3讲】(*2)
- 追问1:final与immutable相同吗?
9、String、StringBuffer、StringBuilder有什么区别?【第5讲】(*3)不可变,中间对象;线程安全;非线程安全
- 追问1:String是基本数据类型吗?
10、int和Integer有什么区别?【第7讲】(*2):包,自动装箱拆箱、值缓存,较小数值范围
11、谈谈你知道的设计模式(*2)?【第14讲】
- 追问1:最常用哪种设计模式?
- 追问2:单例模式是什么,请手动实现(*3)
- 追问3:Spring 等框架中使用了哪些模式?动态代理实现原理?
一、Java 基础
1.1 Java概念原理
1、谈谈你对Java平台的理解?【第1讲】
答:
- 1、相较C语言,Java面向对象,有GC(垃圾收集),不用关心内存分配和回收;
- 2、JVM(跨平台)、JRE(Java基础运行环境)、JDK(Java开发工具包)
1)JVM + 【Java类库、某些模块等】= JRE
2)JRE + 【编译器、诊断等工具】 = JDK
- 3、拓展
……
追问1:面向过程和面向对象有什么区别?
角度 | 面向过程 | 面向对象 |
---|---|---|
特点 | 以分步骤解决问题,用方法组织代码 | 以分类解决问题,用类组织代码。 |
优点 | 性能好 | 工程更加模块化,实现更低耦合和高内聚 |
缺点 | 适应性差、可拓展性与可维护性差 | 类调用需要实例化,开销大 |
特征 | 步骤 | 封装、继承、多态 |
关系:细节用面向过程解决,整体面向对象把控,相辅相成。
追问2:Java中为什么要写None Static Method(非静态方法/实例化方法)?
答:静态方法常驻内存,定义太多会占用大量资源,可能导致溢出,而非静态方法随着实例对象被回收后消失,同时代码不会共享,线程安全。
- 补充:
角度 | Static Method | Non Static Method |
---|---|---|
生命周期 | 与静态类成员一样,装载进内存会常驻,直至JVM关闭 | 实例化后才分配内存,必须通过类实例引用,当实例对象被JVM回收后,跟着消失 |
内存位置 | 静态方法与静态变量创建后使用同一块内存,连续 | 存在内存多个地方,离散 |
效率 | 高 | 低 |
线程安全 | 静态方法(变量)共享代码(数据)段,有并发问题 | 针对确定对象,没问题 |
追问3:Java和Python的区别
角度 | Java | Python |
---|---|---|
类型 | 静态类型,变通实现运行时修改 | 全动态 |
语法 | 面向对象 | 结合函数式编程与面向对象 |
开发周期 | 慢 | 有丰富库,快 |
执行效率 | 性能稳定,扩展性好 | 较差 |
领域 | 服务器、Web、安卓 | 脚本处理、AI、图形图像 |
追问4:Java 高级特性?
-
1)泛型:参数化类型,即把数据类型变成一个可变参数。
-
2)反射:通过 名称来得到对象(类、属性、方法) 的技术。
如:可通过类名-->生成类实例;方法名-->调用方法;属性名-->访问属性值。
-
3)注解:对Java代码打标签,说明作用。
如:读懂代码、格式检查、减少配置、减少重复。可以在编译期检测,也可以运行时反射
追问5:“Java 是解释执行”,这个说法正确吗?
答:不太准确。 Java 的源代码首先通过 Javac 编译成为字节码(bytecode),在运行时,JVM内嵌的解释器将字节码转换成为最终的机器码。
但常见 JVM(如 Hotspot JVM)都提供了 JIT(Just-In-Time)编译器,即动态编译器,能在运行时将热点代码编译成机器码,这种情况下部分热点代码就属于编译执行,而不是解释执行了。
2、动态代理是基于什么原理?【第6讲】(运行时自省,获取类声明属性和方法)
答:反射赋予程序在运行时自省(introspect)的能力,可以直接操作类或者对象,如获取类定义、属性和方法
,甚至可以运行时修改类定义。
动态代理是一种运行时动态构建代理、处理代理方法调用的机制。利用类似机制的场景有 RPC 调用、AOP。
实现方式方面,JDK 自身提供的利用了反射机制,其他的有更高性能的字节码操作机制,类似 ASM、cglib(基于 ASM)、Javassist 等。
3、Java为什么不能多继承?
答:多继承指一个类同时从多于父类那继承行为和特征。图中X方法继承哪个类的方法呢?容易导致事故。
追问1:如何实现多继承?
答:接口或内部类。
4、谈谈接口和抽象类有什么区别?【第13讲】(*3)
- 1)接口是行为的抽象,是抽象方法的集合,可以利用接口达到API定义和实现分离的目的。
- 2)抽象类是不能实例化的类,形式上和一般类没区别,主要是为了代码重用。Java标准库(如collection框架)中很多通用部分(方法实现或成员变量)就被抽取成为抽象类。
接口说明:
1. 不能实例化,不能包含任何非常量成员,任何field都隐含public static final;
2. 没有非静态方法实现,只能是抽象或静态方法。接口举例:java.util.List[Java标准库]
// 实现interface用implements关键词,继承abstract class用extends关键词。
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
//...
}
5、什么是内部类,什么是匿名内部类?
- 1)内部类:将一个类的定义,放在另一个类的定义内部。内部类继承自某个类或实现某个接口,操作外围类的对象。
- 2)匿名内部类:没有名字的内部类。只能使用一次(因为没名字),常用来简化代码编写,
- 3)匿名类使用前提:必须继承一个父类或实现一个接口。
6、重写和重载的区别。(*2)
1)含义
- 重写:子类对父类的方法进行重新实现。即外壳不变,核心重写。
- 重载:每个重载方法(或构造函数)都必须有独一无二的参数类型列表。
2)比较
区别点 | 重写 | 重载 |
---|---|---|
参数列表 | 一定不能修改 | 必须修改 |
返回类型 | 一定不能修改 | 可以修改 |
异常 | 可以减少或删除,一定不能抛出新的或更广的异常 | 可以修改 |
访问 | 一定不能做出更严格的限制,可以降低限制 | 可以修改 |
类型 | 动态绑定,运行时确定 | 静态分配,类加载时确定 |
追问1:多态含义?
- 1)含义 & 作用
多态是同一个行为(接口、消息)可根据对象不同而采取多种不同行为。能消除类型间耦合,具有良好的可扩展性。
- 2)实现方式 & 必要条件
实现方式:重写、接口(插座)、抽象类和抽象方法。
三个必要条件:继承、重写、父类引用指向子类对[Parent p = new Child();
]
// 例1:
package objectandclass;
class A {
public void show(D obj){
System.out.println("A and D");
}
public void show(A obj){
System.out.println ("A and A");
}
}
class B extends A{
public void show(B obj){
System.out.println("B and B");
}
public void show(A obj){
System.out.println("B and A");
}
}
class C extends B{
}
class D extends B{
}
}
... {
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
a1.show(b); // A and A
a1.show(c); // A and A
a1.show(d); // A and D
a2.show(b); // B and A
a2.show(c); // B and A
a2.show(d); // A and D
b.show(b); // B and B
b.show(c); // B and B
b.show(d); // A and D
}
7、Exception和Error有什么区别?【第2讲】:Throwable类;可预料VS不可恢复;可检查+不可检查
1)相同
- Exception和Error都继承了Throwable类,只有Throwable实例可被抛出(throw) 或捕获 (catch)。
2)解释
- Exception是可预料的意外情况,可能且应该被捕获处理;
- Error是正常不太可能出现的情况,大部分出现会导致程序(如JVM)处于不可恢复异常状态,不便于也不需捕获。
3)Exception分类:
- Exception分为可检查异常和不可检查异常,可检查异常在源代码中必须显式地进行处理,这是编译期检查的一部分;不检查异常(NullXXX、ArrayIndexOutofBoundsXXX),通常是可避免的逻辑错误,根据需要捕获。
追问1:你了解哪些 Error、Exception 或者 RuntimeException?
……
追问2:NoClassDefFoundError 和 ClassNotFoundException 有什么区别?
NoClassDefFoundError是一个错误(Error),而ClassNOtFoundException 是一个异常。
- 1)NoClassDefFoundError:编译时存在,JVM或ClassLoader实例加载(正常调用或new新对象)时找不到类定义,那此时会抛出NoClassDefFoundError;
- 2)ClassNotFoundException:动态加载类在类路径中没找到,此时会抛出ClassNotFoundException异常。
追问3:异常处理有哪些原则?
1)捕获特定异常。 尽量不要捕获通用异常,如 Exception。【基本】
2)不要生吞异常。 可能导致难诊断的诡异情况。【基本】
3) Throw early, catch late 原则。
补充:
1. 不捕获某些异常。如RuntimeException 被扩散出来,而不是被捕获。除非深思熟虑,否则不要捕获 Throwable 或者 Error,这样很难保证我们能够正确程序处理 OutOfMemoryError。
2. 分布式系统最好使用产品日志,详细地输出到日志系统里,printStackTrace()无法找到堆栈轨迹(stacktrace)。
8、谈谈final、finally、 finalize有什么不同?【第3讲】(*2)
- 1)final可以修饰类/变量/方法,代表不可继承/修改/重写;
- 2)finally保证重点代码一定执行的一种机制。
如try-catch-finally关闭JDBC连接、unlock锁
; - 3)finalize为了保证对象在垃圾收集前完成特定资源的回收。JDK 9标记弃用。
追问1:final与immutable相同吗?
答:不等同,只保证对象引用不可赋值,但对象行为(如添加)不被影响。
final List<String> strList = new ArrayList<>();
strList.add("Hello");
strList.add("world");
List<String> unmodifiableStrList = List.of("hello", "world"); // List.of本身不可变
unmodifiableStrList.add("again"); // 会抛出错误
说明:
final 只约束 strList 引用不可被赋值,但 strList 对象行为不被 final 影响,添加等操作正常。若希望对象本身不可变,需要相应类支持不可变行为。
9、String、StringBuffer、StringBuilder有什么区别?【第5讲】(*3)不可变,中间对象;线程安全;非线程安全
String 提供构造和管理字符串的基本逻辑,是典型 Immutable
类。所有类、属性是 final,拼接、裁剪等动作会产生新 String 对象。
StringBuffer 是为减少中间对象而提供的类,可用 append/add
把添加字符串,线程安全。StringBuilder 非线程安全,其他和 StringBuffer 相同,大部分情况首选。
追问1:String是基本数据类型吗?
答:不是,String是一个类。
- 补充
- 1)整数:byte, short, int, long(
分别是8、16、32、64位
) - 2)浮点:double, float
- 3)逻辑:boolean
- 4)文本:char
10、int和Integer有什么区别?【第7讲】(*2):包,自动装箱拆箱、值缓存,较小数值范围
- 1)int 是 Java 8 个原始数据类型之一。
- 2)Integer 是 int 的包装类,有 int 字段存储数据,并提供基本操作,如运算、转换等。在Java 5 引入自动装箱和自动拆箱功能(原始类型<=转换=>对象);值缓存(valueOf方法)带来了明显的性能改进。
补充:
1、原始数据类型不是对象。
2、实践发现大部分数据操作都是集中在较小的有限范围,所以引入值缓存,范围:[-128-127]。
11、谈谈你知道的设计模式(*2)?【第14讲】
类别 | 应用目标 | 例子 |
---|---|---|
创建型模式 | 对对象创建过程的各种问题和解决方案的总结 | 工厂模式、单例模式、构建器模式、原型模式 |
结构型模式 | 针对软件设计结构的总结,关注于类、对象继承、组合方式的实践经验 | 桥接模式、适配器模式、装饰者模式、代理模式、组合模式、外观模式、享元模式 |
行为型模式 | 从类或对象之间交互、职责划分等角度总结的模式 | 策略模式、解释器模式、命令模式、观察者模式、迭代器模式、模板方法模式、访问者模式 |
补充:
应用分类 | 中文 | 英文 |
---|---|---|
创建型模式 | 工厂模式 | Factory、Abstract Factory |
单例模式 | Singleton | |
构建器模式 | Builder | |
原型模式 | ProtoType | |
结构型模式 | 桥接模式 | Bridge |
适配器模式) | Adapter | |
装饰者模式 | Decorator | |
代理模式 | Proxy | |
组合模式 | Composite | |
外观模式 | Facade | |
享元模式 | Flyweight | |
行为型模式 | 策略模式 | Strategy |
解释器模式 | Interpreter | |
命令模式 | Command | |
观察者模式 | Observer | |
迭代器模式 | Iterator | |
、模板方法模式 | Template Method | |
访问者模式 | Visitor |
-
追问1:最常用哪种设计模式?
答:单例模式,工厂方法,抽象工厂,策略模式,观察者模式,代理模式…… -
追问2:单例模式是什么,请手动实现(*3)
…… -
追问3:Spring 等框架中使用了哪些模式?动态代理实现原理?
……
二、参考
1、Java基础:static方法与非static方法的区别
2、Java高级特性入门——泛型、反射和注解
3、java提高篇(九)-----实现多重继承
4、Java 8 默认方法和多继承
5、Java重写和重载的区别
6、JAVA重写和重载
7、Java 重写(Override)与重载(Overload)
8、一篇文章让你彻底了解Java内部类
9、Java内部类和匿名内部类的用法
10、java中的匿名内部类总结
11、ClassNotFoundException和NoClassDefFoundError的区别