- Java中的内部类(Inner Class)和外部类(Outer Class)有什么区别?内部类有哪些类型
- 内部类是定义在另一个类里面的类。
- 外部类则是独立定义的类。
- 内部类可以分为四种:成员内部类、局部内部类、匿名内部类和静态内部类。
- Java中的注解(Annotation)是什么?它有哪些用途
- 注解是Java提供的一种对代码进行标记和说明的机制,它不会对代码的执行产生直接影响。
- 注解可以用于生成文档、编译检查、代码分析等。
- Java内置了一些注解,如
@Override
、@Deprecated
等,同时也支持自定义注解。
- Java中的枚举(Enum)类型是什么?它有哪些特性?
- 枚举类型是一种特殊的类,用于表示一组固定的常量。
- 枚举类型可以包含字段、方法和构造函数,但构造函数通常是私有的,以防止外部代码创建枚举类型的实例。
- 枚举类型在编译时会被特殊处理,们既是一种类类型,又是一种基本数据类型。
- Java中的String类是不可变的,这意味着什么?有什么优势
- 不可变性意味着一旦String对象被创建,其内部状态(即字符序列)就不能被改变。
- 这种不可变性带来了很多优势,如线程安全(因为不需要同步)、可以安全地缓存字符串常量、以及可以在字符串连接时重用原有对象以减少内存分配和垃圾回收的开销。
- Java中的数组(Array)和ArrayList有什么区别
- 数组是固定大小的,一旦创建就不能改变其长度。
- ArrayList是动态数组的实现,可以根据需要自动调整其大小。
- ArrayList提供了更多的方法和功能,如
add()
、remove()
等,而数组则不支持这些操作。 - ArrayList在内部使用数组来存储元素,但提供了额外的逻辑来处理动态扩容等问题
- Java中的hashCode()方法的作用是什么?它与equals()方法有什么关系
hashCode()
方法用于获取对象的哈希码,它是一个整数。- 哈希码在Java的集合框架(如HashMap、HashSet等)中被广泛使用,以优化对象的查找、插入和删除等操作。
- 根据Java的规范,如果两个对象通过
equals()
方法比较相等,那么它们的hashCode()
方法必须返回相同的整数值。
- Java中的可变参数(Varargs)是什么?如何使用
- 可变参数允许在调用方法时传入不定长度的参数。
- 在方法定义中,可变参数必须是方法的最后一个参数,并且前面可以有零个或多个普通参数。
- 可变参数在编译时会被转换为对应类型的数组。
- 例如,
public void printNumbers(int... numbers) { ... }
表示该方法可以接受任意数量的int
类型参数。
- Java中的反射(Reflection)是什么?它有哪些用途和限制
- 反射是Java提供的一种强大的机制,允许程序在运行时动态地访问和操作类和对象的属性、方法等信息。
- 反射的主要用途包括:在运行时创建对象、调用方法、访问字段、检查类的属性和方法等。
- 然而,反射也带来了一些限制和性能开销,如破坏了封装性、增加了安全性风险以及可能导致性能下降等。
- Java中的类加载器(ClassLoader)是什么?它有什么作用
- 类加载器是Java中用于加载类的机制。
- 它负责将类的字节码文件(.class文件)加载到JVM中,并转换成JVM能够识别的类对象。
- Java中的类加载器采用双亲委派模型来加载类,即当一个类加载器需要加载一个类时,它首先会把这个请求委托给它的父类加载器去完成,只有当父类加载器无法加载这个类时,子类加载器才会尝试自己去加载。
- 这种双亲委派模型的好处是保证了Java核心库的类型安全,避免了类的重复加载,同时也使得Java的类加载机制更加灵活。
- Java中主要有三种类加载器:
- 启动类加载器(Bootstrap ClassLoader):负责加载Java核心库(如
rt.jar
),它是C++编写的,没有继承自java.lang.ClassLoader
。 - 扩展类加载器(Extension ClassLoader):负责加载扩展库中的类,这些库位于
$JAVA_HOME/lib/ext
目录下,或者是通过系统属性java.ext.dirs
指定的目录。 - 系统类加载器(System ClassLoader):也称为应用类加载器(Application ClassLoader),它负责加载用户类路径(
classpath
)上的类。 - 开发者还可以根据需要自定义类加载器,以实现特定的加载策略或解决类加载冲突等问题。
- Java中的包装类(Wrapper Classes)是什么?它们与基本数据类型的关系是什么
- 包装类是将基本数据类型封装成对象的形式,以便能够使用对象的方法来操作基本数据类型的值。例如,
Integer
是int
的包装类。 - 它们之间的关系是,包装类提供了基本数据类型所不具备的功能,如类型转换、比较大小等。同时,自动装箱和拆箱机制使得基本数据类型和包装类之间的转换变得非常方便。
- Java中的位运算符有哪些?请解释它们的作用。
- 位运算符包括按位与(&)、按位或(|)、按位异或(^)、按位取反(~)、左移(<<)、右移(>>)和无符号右移(>>>)。
- 它们的作用是在二进制层面上对数值进行操作,如按位与操作会将两个数的二进制表示中对应位都为1的位设置为1,其余位设置为0。
- Java中的switch语句支持哪些数据类型
- 在Java 7及之前,switch语句只支持
byte
、short
、char
、int
以及枚举类型(enum)。 - 从Java 7开始,switch语句增加了对
String
类型的支持。 - 注意,虽然
long
、float
、double
和boolean
等类型在Java中是基本数据类型,但它们并不被switch语句直接支持。
- Java中的断言(Assertion)是什么?它有什么用途
- 断言是Java中的一种调试辅助工具,用于在代码中设置检查点,以验证程序的某个状态是否满足预期条件。
- 当断言失败时,程序会抛出一个
AssertionError
异常(默认情况下,如果JVM启用了断言,则断言失败会抛出异常;如果未启用断言,则断言检查会被忽略)。 - 断言主要用于开发和测试阶段,帮助开发者快速定位问题;但在生产环境中,由于性能考虑,通常会关闭断言。
- Java中的this关键字和super关键字分别有什么作用?
this
关键字用于引用当前对象的成员(包括变量和方法)。它也可以用于在构造方法中调用另一个构造方法(但必须是第一条语句)。super
关键字用于引用当前对象的直接父类对象及其成员(包括变量和方法)。它主要用于访问被子类隐藏的父类成员,以及在子类的构造方法中调用父类的构造方法。
- Java中的static块(静态块)是什么?它有什么用途?
- 静态块是在类被加载到JVM时执行的代码块,它只会被执行一次。
- 静态块通常用于初始化静态变量或执行只需要执行一次的静态初始化操作。
- 注意,静态块不是类的成员,因此它不能访问类的非静态成员(除非在静态块中创建类的实例)。
- Java中的finalize()方法是做什么的?它在垃圾回收过程中扮演什么角色?
finalize()
方法是Object
类的一个方法,它可以被子类覆盖以提供对象被销毁前的清理工作。- 然而,需要注意的是,从Java 9开始,
finalize()
方法已经被标记为过时(deprecated),因为现代垃圾回收器提供了更好的清理机制,并且finalize()
方法的使用可能导致性能问题。 - 在早期Java版本中,
finalize()
方法可能被JVM的垃圾回收器调用,以执行对象的清理工作。但在实际开发中,应尽量避免使用finalize()
方法,而是采用更现代的清理机制(如try-with-resources
语句或显式的清理方法)。
- Java中的内部类可以访问外部类的哪些成员?
- 内部类(无论是成员内部类、局部内部类还是匿名内部类)都可以访问其外部类的所有成员(包括私有成员),前提是这些成员在内部类访问它们的时候是可见的(即没有超出它们的作用域)。
- 但是,外部类不能直接访问内部类的成员,除非通过内部类的对象来访问。