Java基础
1. Java语言特性
1.1 面向对象的特性
- 封装:将数据和操作数据的方法绑定在一起,对外部隐藏对象的具体实现细节
- 继承:允许创建一个类作为另一个类的基础,继承父类的属性和方法
- 多态:同一个操作作用于不同的对象,可以有不同的解释和执行结果
示例代码:
// 封装示例
public class Student {
private String name; // 私有属性
private int age;
// 公共方法访问私有属性
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
// 继承示例
public class Person {
protected String name;
public void eat() {
System.out.println("Person eating");
}
}
public class Student extends Person {
private int studentId;
@Override
public void eat() {
System.out.println("Student eating");
}
}1.2 Java平台特性
- 跨平台性:Write Once, Run Anywhere
- 安全性:沙箱安全机制、字节码验证
- 简单性:相比C++去除了指针、运算符重载等复杂特性
2. 基本数据类型
2.1 八种基本数据类型
- 整型:byte(8位)、short(16位)、int(32位)、long(64位)
- 浮点型:float(32位)、double(64位)
- 字符型:char(16位)
- 布尔型:boolean
// 基本数据类型示例
public class DataTypeDemo {
public static void main(String[] args) {
byte b = 127;
short s = 32767;
int i = 2147483647;
long l = 9223372036854775807L;
float f = 3.14f;
double d = 3.14159265359;
char c = 'A';
boolean bool = true;
}
}2.2 包装类型
- 每个基本类型都有对应的包装类型
- 自动装箱和拆箱机制
Integer num = 100; // 自动装箱
int n = num; // 自动拆箱3. 面试常考题
3.1 基本数据类型和包装类型的区别?
-
存储位置
- 基本数据类型:存储在栈中
- 包装类型:存储在堆中
-
默认值
- 基本数据类型:有默认值(如int为0)
- 包装类型:默认值为null
-
比较方式
- 基本数据类型:使用==比较值
- 包装类型:使用equals()比较值,==比较引用
3.2 String类的不可变性是什么?
String类的不可变性体现在:
- String类被final修饰,不能被继承
- 内部的char数组被private final修饰
- 不提供修改内部数组的方法
// String不可变性示例
String str = "Hello";
str = str + " World"; // 实际上创建了新的String对象3.3 ==和equals的区别?
-
==
- 比较基本数据类型:比较值
- 比较引用类型:比较引用(内存地址)
-
equals()
- Object类的equals()方法默认与==相同
- String等类重写了equals()方法,比较内容
String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(str1 == str2); // false
System.out.println(str1.equals(str2)); // true4. 最佳实践
-
合理使用基本类型和包装类型
- 频繁使用的小数据,优先使用基本类型
- 需要存储null或使用泛型时,使用包装类型
-
String操作优化
- 大量字符串拼接时使用StringBuilder
- 多线程环境下使用StringBuffer
-
避免可变性带来的问题
- 重要的可变对象考虑深拷贝
- 注意对象作为HashMap键时的不可变性
// 字符串拼接最佳实践
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append("item").append(i);
}
String result = sb.toString();5. 反射机制
5.1 什么是反射?
反射机制允许程序在运行时获取任何类的内部信息,并能直接操作任意对象的内部属性及方法。
// 反射示例
public class ReflectionDemo {
public static void main(String[] args) throws Exception {
// 获取类的Class对象
Class<?> clazz = Class.forName("com.example.Student");
// 创建实例
Object obj = clazz.newInstance();
// 获取方法并调用
Method method = clazz.getMethod("setName", String.class);
method.invoke(obj, "张三");
}
}5.2 反射的应用场景
-
框架开发
- Spring的依赖注入
- MyBatis的对象映射
- JUnit的测试用例加载
-
动态代理
- AOP面向切面编程
- RPC远程调用
6. 注解
6.1 什么是注解?
注解是一种代码级别的说明,可以对程序做出解释或者指示。
// 自定义注解示例
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
String value() default "";
}
// 使用注解
public class TestDemo {
@Test("测试方法")
public void testMethod() {
// 测试代码
}
}6.2 元注解有哪些?
- @Target:注解的作用目标
- @Retention:注解的生命周期
- @Documented:注解是否包含在JavaDoc中
- @Inherited:注解是否可以被继承
7. 泛型
7.1 什么是泛型?为什么要使用泛型?
泛型提供了编译时类型安全检测机制,可以在编译时检测到非法的类型。
// 泛型类示例
public class Box<T> {
private T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
}
// 使用泛型类
Box<String> stringBox = new Box<>();
stringBox.set("Hello World");7.2 泛型通配符
-
上界通配符 <? extends Type>
- 用于限制泛型类型的上界
- 只能读取,不能写入
-
下界通配符 <? super Type>
- 用于限制泛型类型的下界
- 可以写入,读取时只能用Object接收
8. 异常处理
8.1 异常体系结构
- Throwable
- Error:严重错误,程序无法处理
- Exception:可以被程序处理的异常
// 异常处理示例
public class ExceptionDemo {
public static void main(String[] args) {
try {
// 可能抛出异常的代码
int result = divide(10, 0);
} catch (ArithmeticException e) {
// 处理异常
System.out.println("除数不能为0");
} finally {
// 清理资源
System.out.println("finally块总是执行");
}
}
public static int divide(int a, int b) {
return a / b;
}
}8.2 受检异常和非受检异常的区别?
-
受检异常(Checked Exception)
- 必须显式处理或声明抛出
- 代表可以恢复的异常情况
- 如:IOException、SQLException
-
非受检异常(Unchecked Exception)
- 不需要显式处理或声明
- 代表编程错误
- 如:NullPointerException、ArrayIndexOutOfBoundsException