1.包装类型的缓存机制了解么?
指部分包装类在创建对象时,会将一定范围内的对象缓存起来,当再次使用相同值创建对象时,优先从缓存中获取,而不是重新创建新对象。【提高性能】【节省内存】
列举几个常见的包装类缓存机制:
(1)Integer
类在 -128
到 127
这个范围内有缓存机制。当使用 Integer.valueOf(int)
方法创建 Integer
对象时,如果值在这个范围内,会直接从缓存中获取对象,否则会创建新对象。
Integer a = Integer.valueOf(100);
Integer b = Integer.valueOf(100);
System.out.println(a == b); // 输出 true,因为从缓存中获取的同一个对象Integer c = Integer.valueOf(200);
Integer d = Integer.valueOf(200);
System.out.println(c == d); // 输出 false,因为值不在缓存范围内,创建了新对象
(2)Byte
、Short
和 Long
类也有类似的缓存机制,缓存范围都是 -128
到 127
。
Byte byte1 = Byte.valueOf((byte) 10);
Byte byte2 = Byte.valueOf((byte) 10);
System.out.println(byte1 == byte2); // 输出 trueShort short1 = Short.valueOf((short) 100);
Short short2 = Short.valueOf((short) 100);
System.out.println(short1 == short2); // 输出 trueLong long1 = Long.valueOf(120L);
Long long2 = Long.valueOf(120L);
System.out.println(long1 == long2); // 输出 true
(3)Character
类会缓存从 \u0000
到 \u007F
(即 0
到 127
)的字符对象。
Character char1 = Character.valueOf('A');
Character char2 = Character.valueOf('A');
System.out.println(char1 == char2); // 输出 true
(4)Boolean
类会缓存 true
和 false
两个对象。
Boolean bool1 = Boolean.valueOf(true);
Boolean bool2 = Boolean.valueOf(true);
System.out.println(bool1 == bool2); // 输出 true
【注意】只有使用 valueOf
方法创建对象时才会触发缓存机制,如果使用 new
关键字创建对象,无论值是否在缓存范围内,都会创建新对象。
2. 自动装箱与拆箱了解吗?原理是什么?
Java的自动装箱和拆箱是Java 5 引入的,主要用于简化基本数据类型和对应的包装类之间的转换操作。
自动装箱:指基本类型自动转换成对应的包装类对象。如 int 自动转 Integer。
自动拆箱:指包装类对象自动转换成对应的基本类型。如 Integer自动转int。
// 自动装箱
int num1 = 10;
Integer num2 = num1;// 自动拆箱
Integer num3 = 20;
int num4 = num3;
自动装箱和拆箱的原理:
自动装箱原理:在编译阶段,编译器会调用包装类的valueOf()方法来实现自动装箱。
例如,上述代码中的Integer num2 = num1;
在编译后实际上会变成Integer num2 = Integer.valueOf(num1);。
自动拆箱:在编译阶段,编译器会调用包装类的xxxValue()方法来实现自动拆箱。
像int num4 = num3;
在编译后会变为int num4 = num3.intValue();。
包装类的缓存机制,又在这里得到了验证。
3. 浅拷贝和深拷贝区别了解吗?什么是引用拷贝?
浅拷贝、深拷贝和引用拷贝是三种不同的对象复制方式。
(1)引用拷贝仅仅是复制对象的引用,而不会创建新的对象。也就是说,原对象和复制后的对象都指向内存中的同一个实例。因此,对其中一个对象的修改会反映到另一个对象上。
(2)浅拷贝会创建一个新的对象,然后将原对象的非静态字段复制到新对象中。如果字段是基本数据类型,就直接复制其值;如果字段是引用类型,只复制引用,而不复制对象本身。这意味着原对象和浅拷贝对象中的引用类型字段会指向同一个对象(也就是说原对象的内部类会直接引用)。
要实现浅拷贝,可以让类实现 Cloneable
接口并重写 clone()
方法。
(3)深拷贝同样会创建一个新的对象,并且会递归地复制原对象的所有字段,包括引用类型的字段。这意味着原对象和深拷贝对象中的引用类型字段指向不同的对象,对一个对象的修改不会影响到另一个对象。
要实现深拷贝,可以通过序列化和反序列化来完成,也可以手动递归地复制所有引用类型的字段。
4. 谈谈对 Java 注解的理解,解决了什么问题?
注解可以看作是一种特殊的标记,它可以应用于包、类、方法、字段等元素上,以提供额外的信息。注解通过 @
符号来标识,例如 @Override
、@Deprecated
等。Java 提供了一些内置的注解,同时开发者也可以自定义注解。
注解解决的问题:
(1)编译时检查:编译器会检查被 @Override
注解标记的方法是否真的重写了父类的方法,如果没有则会报错。这样可以避免因方法名拼写错误或方法签名不匹配而导致的潜在问题。
(2)代码生成:在一些框架中,注解可以用于生成代码。如 Lombok
(3)配置信息管理:注解可以用于替代传统的配置文件,将配置信息直接嵌入到代码中。例如,Spring 框架使用 @Component
、@Service
、@Repository
等注解来标识组件,将组件的配置信息与代码紧密结合,提高了代码的可维护性。
(4)运行时信息的获取:通过反射机制,在运行时获取注解的信息,并根据这些信息执行相应的操作。例如,JUnit 框架使用 @Test
注解来标记测试方法,在运行测试时,JUnit 会通过反射查找所有被 @Test
注解标记的方法并执行。
5. Exception 和 Error 有什么区别?
Exception
和 Error
都继承自 Throwable
类
Exception
表示程序运行时可能出现的可处理的异常情况。开发人员能够通过捕获和处理这些异常。
Error
表示系统级别的错误。通常是由 JVM或者底层系统出现问题引发的。
应用场景
- Exception:
- 受检查异常:在编译时就需要被处理的异常,若不处理,程序将无法通过编译,例如
IOException
、SQLException
等。 - 运行时异常:编译时不需要强制处理,例如
NullPointerException、
ArrayIndexOutOfBoundsException
等。
- 受检查异常:在编译时就需要被处理的异常,若不处理,程序将无法通过编译,例如
- Error:一般是系统级的错误,常见的有
OutOfMemoryError
、StackOverflowError
等
6. Java 反射?反射的缺点?反射的应用场景?
反射是什么?
反射(Reflection)是 Java 提供的一种动态机制,允许程序在运行时获取类的元数据(如类名、方法、字段、构造器等),并动态操作类或对象(如实例化对象、调用方法、访问私有成员等)。其核心是通过 Class
对象实现,关键 API 包括:
-
Class
类:表示类的元数据。 -
Method
、Field
、Constructor
:分别表示方法、字段和构造器。
示例:通过类名动态创建对象:
Class<?> clazz = Class.forName("com.example.User");
Object user = clazz.newInstance();
反射的缺点
-
性能开销:反射调用涉及动态解析和 JVM 优化限制(如无法内联方法),性能比直接调用低。但通过缓存
Method
对象或使用setAccessible(true)
关闭安全检查可缓解。 -
破坏封装性:可访问私有成员(如
private
方法或字段),可能导致代码安全隐患。 -
代码复杂度:反射代码冗长,需处理大量异常(如
ClassNotFoundException
),降低可读性和维护性。 -
兼容性风险:反射依赖类的内部细节(如方法名、参数列表),若类结构变更(如版本升级),反射代码可能失效。
-
泛型擦除:反射无法直接获取泛型类型信息(如
List<String>
在运行时变为List
)。
反射的应用场景
-
框架开发:
-
Spring 依赖注入:通过反射实例化 Bean 并注入属性。
-
ORM 框架(如 Hibernate):将数据库结果映射到 Java 对象。
-
动态代理(如 AOP):生成代理类拦截方法调用。
-
-
序列化/反序列化:如 Jackson 通过反射读取对象字段生成 JSON。
-
测试工具:JUnit 使用反射调用测试方法。
-
插件化架构:动态加载类(如通过配置文件的类名实例化对象)。
-
IDE 和调试工具:实时获取对象信息(如变量值、方法列表)。
7. Java 泛型了解么?什么是类型擦除?介绍⼀下常⽤的通配符?
Java泛型&通配符