【Java八股文总结 — 包学会】(一)java基础

1. java的基本数据类型、包装类型

java常见的基本数据类型有:byte、short、int、long、double、float、char、boolean

对应的包装类型有:Byte、Short、Integer、Long、Double、Float、Character、Boolean

二者的主要区别:基础类型存储在栈中,包装类型存储在堆中;基础类型有默认值比如int默认为0,包装类型默认为null,因为是对象;基础数据类型只能进行基本的算术操作和逻辑操作,包装类型提供许多方法和属性,可以进行更复杂的操作;包装类型还能自动装箱和拆箱。

2. 装箱和拆箱的原理和作用

装箱:int 变为 Integer,将基本数据类型转变为包装类型的过程

拆箱:Integet 变为 int,将包装类型转变为基本数据类型的过程

public class demo1 {
    public static void main(String[] args) {
        // 自动装箱
        int x = 5;
        Integer y = x;
        System.out.println(y);
        // 手动装箱
        Integer y1 = Integer.valueOf(x);
        System.out.println(y1);
        // 自动拆箱
        Integer x1 = 6;
        int a = x1;
        System.out.println(a);
        // 手动拆箱
        int a1 = x1.intValue();
        System.out.println(a1);
    }
}

作用:java集合框架不能存储基本数据类型,只能存储对象,装箱和拆箱能让基本数据类型在集合中使用更加方便。自动装箱和拆箱可以减少代码的显示转换,让代码更加易懂。

3. String、StringBuffer、StringBuilder的区别

String是不可变的、StringBuffer和StringBuilder是可变的。String和StringBuffer是线程安全的、StringBuilder是非线程安全的。

那为什么String是不可变的呢?

public final class String

    implements java.io.Serializable, Comparable<String>, CharSequence {

    /** The value is used for character storage. */

    private final char value[];

}    

  • 保存字符串的数组被 final 修饰且为私有的,并且String 类没有提供/暴露修改这个字符串的方法;
  • String 类被 final 修饰导致其不能被继承,进而避免了子类破坏 String 不可变。

String和StringBuilder创建对象的数量区别

String result = "A" + "B" + "C";

使用 String 拼接、编译器会自动转换为 StringBuilder 实现:

String result = new StringBuilder().append("A").append("B").append("C").toString();

创建的对象:

1个 StringBuilder 对象

toString() 时创建 1个新的 String 对象

常量池中的 “A”、“B”、“C”(首次使用时创建,此处假设已存在)

总计:2个新对象(1个StringBuilder + 1个String)。

显式使用 StringBuilder

StringBuilder sb = new StringBuilder();
sb.append("A").append("B").append("C");
String result = sb.toString();

创建的对象:

1个 StringBuilder 对象(内部创建1个 char[16])

toString() 时创建 1个新的 String 对象

总计:2个新对象(与编译器优化后的 String 拼接一致)。

String result = "";
for (int i = 0; i < N; i++) {
    result += "a"; // 每次循环产生新对象
}

使用 String 拼接(低效!)每次循环的实质:

result = new StringBuilder().append(result).append("a").toString();

创建的对象:

循环 N 次,每次创建:

1个 StringBuilder 对象

1个新的 String 对象(由 toString() 生成)

总计:2N个新对象(N个StringBuilder + N个String)。

使用 StringBuilder(高效!)

StringBuilder sb = new StringBuilder();
for (int i = 0; i < N; i++) {
    sb.append("a");
}
String result = sb.toString();

创建的对象:

1个 StringBuilder 对象(初始 char[16])

扩容时的新数组(若长度超过当前容量):

扩容次数 ≈ log₂(N/16)(按指数扩容)

每次扩容创建 1个新的 char[]

toString() 时创建 1个新的 String 对象

总计:

固定1个 StringBuilder 对象

1个 String 对象

少量 char[] 数组(通常远小于 N)

为什么StringBuffer是线程安全

通过 synchronized 关键字 在关键方法上实现了同步锁机制。

4. String转换Integer原理

public class demo2 {

    public static void main(String[] args) {
        String content = "11111";

        int count1 = Integer.parseInt(content);
        System.out.println(count1);
        Integer count2 = Integer.valueOf(content);
        System.out.println(count2);
        Integer count3 = new Integer(content);
        System.out.println(count3);
    }
}
public static int parseInt(String s) throws NumberFormatException {
    if (s == null) {
        throw new NumberFormatException("null");
    }

    int result = 0;
    boolean negative = false;
    int i = 0, len = s.length();

    // 处理负号
    char firstChar = s.charAt(0);
    if (firstChar == '-') {
        negative = true;
        i++;
    }

    while (i < len) {
        int digit = s.charAt(i++) - '0';  // 将字符 '1' 转为数字 1
        if (digit < 0 || digit > 9) throw new NumberFormatException();
        result = result * 10 + digit;
    }

    return negative ? -result : result;
}

  • s.charAt(i) - ‘0’:通过字符 ASCII 值转换成整数(比如 ‘3’ 的 ASCII 是 51,‘0’ 是 48,51-48=3)
  • 字符逐个读取并计算:result = result * 10 + digit
  • 支持负数
  • 抛出异常:如果不是合法数字字符,就抛出 NumberFormatException

Integer.valueOf() 有缓存机制吗?

有,范围是 [-128, 127]

反过来 Integer → String 怎么转?

 String s = String.valueOf(666);
 System.out.println(s);
 String s2 = Integer.toString(777);
 System.out.println(s2);

5. 接口和抽象类的区别

接口:使用interface关键字定义,一个类可以实现多个接口,一个接口也可以继承多个接口,用于定义一组不相关类的公共行为,适合API设计,更适合定义能力接口。

抽象类:使用abstract关键字定义,一个类只能继承一个抽象类,用于定义一组相关类的公共行为,适合定义类之间的结构层次,提供公共的实现和状态

当强调 “做什么” 且实现者无关时 → 用接口

当需要 “是什么” 且共享代码时 → 用抽象类

现代 Java 中:接口为主,抽象类为辅(尤其需要默认方法后)

// 接口 - 自动为 public static final
interface Flyable {
    int MAX_ALTITUDE = 10000; // 常量
}

// 抽象类 - 常规变量
abstract class Bird {
    protected String species; // 实例变量
    private static int count; // 静态变量
}
// 接口支持多继承
interface Robot extends Movable, Programmable {
    void recharge();
}

// 抽象类单继承
abstract class Sparrow extends Bird implements Flyable {
    // 继承Bird + 实现Flyable
}

接口(Interface)定义“能做什么”,是纯行为契约(可多继承),用于声明跨类别的能力;抽象类(Abstract Class)定义“是什么”,是部分实现的类模板(单继承),用于封装相关类的共性代码和状态。优先用接口解耦,需要代码复用时用抽象类。

// 接口:定义行为契约(能做什么)
interface Flyable {
    void fly(); // 抽象方法(默认public abstract)
    default void land() { // 默认方法(Java8+)
        System.out.println("准备降落...");
    }
}

// 抽象类:定义基础实现(是什么)
abstract class Bird {
    protected String name;
    
    public Bird(String name) {
        this.name = name;
    }
    
    // 具体方法:所有鸟类共享的实现
    public void breathe() {
        System.out.println(name + "正在呼吸空气");
    }
    
    // 抽象方法:需要子类实现
    public abstract void makeSound();
}

// 具体类:继承抽象类 + 实现接口
class Sparrow extends Bird implements Flyable {
    public Sparrow() {
        super("麻雀");
    }
    
    // 实现抽象类的方法
    @Override
    public void makeSound() {
        System.out.println("叽叽喳喳!");
    }
    
    // 实现接口的方法
    @Override
    public void fly() {
        System.out.println(name + "正在低空飞行");
    }
    
    // 覆盖默认方法
    @Override
    public void land() {
        System.out.println("收起翅膀着陆");
    }
}

// 演示类
public class BirdDemo {
    public static void main(String[] args) {
        Sparrow sparrow = new Sparrow();
        
        // 调用抽象类方法
        sparrow.breathe();  // 输出:麻雀正在呼吸空气
        sparrow.makeSound();// 输出:叽叽喳喳!
        
        // 调用接口方法
        sparrow.fly();      // 输出:麻雀正在低空飞行
        sparrow.land();     // 输出:收起翅膀着陆
        
        // 多态演示
        Bird myBird = sparrow;
        myBird.makeSound(); // 输出:叽叽喳喳!
        
        Flyable flyingThing = sparrow;
        flyingThing.fly(); // 输出:麻雀正在低空飞行
    }
}

6. java的对象的创建过程

public class MyClass {
    private int value = 10;  // 实例变量初始化
    private static int count = 0;  // 静态变量
    
    // 实例初始化块
    {
        System.out.println("实例初始化块执行");
        value = 20;
    }
    
    // 静态初始化块
    static {
        System.out.println("静态初始化块执行");
        count = 100;
    }
    
    // 构造方法
    public MyClass() {
        System.out.println("构造方法执行");
        value = 30;
    }
}

public class Main {
    public static void main(String[] args) {
        // 对象创建过程从这里开始
        MyClass obj = new MyClass();
        System.out.println("最终 value 值: " + obj.value);
    }
}

1️⃣ 类加载(首次使用时)
检查类是否已加载

若未加载,则执行类加载过程:

加载 → 验证 → 准备 → 解析 → 初始化

静态初始化:

执行静态变量初始化和静态初始化块

输出:静态初始化块执行

📝 注意:类加载只发生一次,后续创建对象时不再重复

2️⃣ 内存分配
JVM 在堆内存中分配对象所需空间

空间大小在类加载后即可确定(包括所有实例变量)

3️⃣ 初始化零值
将所有实例变量设为默认值:

数值类型:0

布尔类型:false

引用类型:null

4️⃣ 设置对象头
创建对象头(Object Header),包含:

Mark Word:哈希码、GC 信息、锁状态等

类型指针:指向类元数据(方法区中)

数组长度(如果是数组)

5️⃣ 执行实例初始化
按顺序执行初始化操作:

实例变量显式初始化

java
value = 10; // 初始化为10
实例初始化块执行

java
{
System.out.println(“实例初始化块执行”);
value = 20; // 修改为20
}
输出:实例初始化块执行

构造方法执行

java
public MyClass() {
System.out.println(“构造方法执行”);
value = 30; // 修改为30
}
输出:构造方法执行

6️⃣ 建立引用
将栈中的变量 obj 指向堆中的对象地址

对象创建完成,可以使用

7. 什么是深克隆、浅克隆,java函数传参是值传递还是引用传递

深克隆:复制对象的值类型属性以及递归复制引用类型属性。修改新对象的引用类型属性不会影响原对象
浅克隆:复制对象的值类型属性,对于引用类型属性,只复制引用。修改新对象的引用类型属性影响原对象

import java.util.Arrays;

class Address implements Cloneable {
    String city;
    
    public Address(String city) {
        this.city = city;
    }
    
    // 重写 clone 方法实现浅克隆
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

class Person implements Cloneable {
    String name;
    int age;
    Address address;  // 引用类型
    String[] hobbies; // 数组类型
    
    public Person(String name, int age, Address address, String[] hobbies) {
        this.name = name;
        this.age = age;
        this.address = address;
        this.hobbies = hobbies;
    }
    
    // 浅克隆实现
    @Override
    protected Object shallowClone() throws CloneNotSupportedException {
        return super.clone();
    }
    
    // 深克隆实现
    @Override
    protected Object deepClone() throws CloneNotSupportedException {
        Person cloned = (Person) super.clone();
        
        // 克隆引用类型成员
        cloned.address = (Address) address.clone();
        
        // 克隆数组(创建新数组)
        cloned.hobbies = hobbies.clone();
        
        return cloned;
    }
    
    @Override
    public String toString() {
        return "Name: " + name + 
               ", Age: " + age + 
               ", City: " + address.city + 
               ", Hobbies: " + Arrays.toString(hobbies);
    }
}

public class CloneExample {
    public static void main(String[] args) throws CloneNotSupportedException {
        Address addr = new Address("Beijing");
        String[] hobbies = {"Reading", "Swimming"};
        Person original = new Person("Alice", 25, addr, hobbies);
        
        // 浅克隆
        Person shallowCopy = (Person) original.shallowClone();
        
        // 深克隆
        Person deepCopy = (Person) original.deepClone();
        
        // 修改原始对象的属性
        original.name = "Bob";
        original.age = 30;
        original.address.city = "Shanghai";
        original.hobbies[0] = "Gaming";
        
        System.out.println("Original: " + original);
        System.out.println("Shallow Copy: " + shallowCopy); // 引用类型被修改
        System.out.println("Deep Copy: " + deepCopy);       // 保持独立
    }
}

在java中,函数传递的机制是基于值传递的(对于基本类型参数和引用类型参数都是基于值传递的)。

对于引用类型也是传递值的拷贝,它只是在函数内部通过引用修改对象的内容,但不能改变引用本身指定对象

class Person {
    String name;
    
    public Person(String name) {
        this.name = name;
    }
}

public class PassByValueExample {
    public static void main(String[] args) {
        // 情况1:基本类型参数传递
        int num = 10;
        System.out.println("基本类型修改前: " + num); // 10
        modifyPrimitive(num);
        System.out.println("基本类型修改后: " + num); // 10 (未改变)
        
        // 情况2:引用类型参数传递 - 修改对象内容
        Person person = new Person("Alice");
        System.out.println("引用类型修改前: " + person.name); // Alice
        modifyObjectContent(person);
        System.out.println("引用类型修改后: " + person.name); // Bob (内容被修改)
        
        // 情况3:引用类型参数传递 - 尝试改变引用
        System.out.println("尝试改变引用前: " + person.name); // Bob
        tryChangeReference(person);
        System.out.println("尝试改变引用后: " + person.name); // Bob (引用未改变)
    }
    
    // 情况1: 基本类型参数传递 - 值拷贝
    public static void modifyPrimitive(int value) {
        value = 20; // 修改的是副本
    }
    
    // 情况2: 引用类型参数传递 - 通过引用修改对象内容
    public static void modifyObjectContent(Person p) {
        p.name = "Bob"; // 修改的是原对象的内容
    }
    
    // 情况3: 引用类型参数传递 - 尝试改变引用本身
    public static void tryChangeReference(Person p) {
        p = new Person("Charlie"); // 改变的是引用的副本
        p.name = "David"; // 修改的是新对象
    }
}

8. &与&&区别、==与equals的区别

在Java中,&和&&的核心区别在于短路行为:&&是短路与运算符,当左侧表达式为false时直接跳过右侧计算,更高效安全,适用于条件判断;&是非短路与运算符,始终计算两侧表达式,还可作为位运算符处理整数二进制操作。简单来说:条件判断用&&避免不必要计算(如if(a != null && a.isEmpty())),需要强制计算两侧或位运算时用&。

==:是一个比较操作符,比较的是引用(内存地址)是否相同,可以用于比较基本数据类型和对象的引用。

equals:是Object类中的一个方法,比较两个对象的内容是否相同。但Object类默认情况下equlas方法与==用法相同,但许多类重写equals方法用于比较对象内容是否相同比如String、Integer等。

9.hashcode与quals的区别,为什么重写equals方法要重写hashcode

hashcode:这个方法返回一个哈希码。Object类中默认的是将对象的内存地址转换为一个整数。
equals:这给方法比较的是两个对象的内容是否相同(在重写的情况下),默认的Object比较的是引用和==一样。

如果两个对象的根据equals方法是相同的,那么他们的hashcode的值也要相同。只重写equals方法步重写hashcode方法,会导致在哈希表中查找、删除、插入对象出现问题。(同一个对象多次调用hashcode值应该返回相同的值)

10. this、final、finally、finalize的区别

在Java中,this 是当前对象的引用(用于访问实例成员或调用构造器),final 是修饰符(使变量不可变、方法不可重写、类不可继承),finally 是异常处理块(无论是否异常都必执行,用于资源清理),而**finalize** 是Object类的废弃方法(GC前回调,Java 9+已弃用)。四者本质不同:this指向对象,final强制不变性,finally保证代码执行,finalize是过时的回收钩子。

11. 四种访问修饰符是什么,有什么区别

在Java中,public(所有类可访问)、protected(同包类+子类可访问)、默认(包级)(同包类可访问)、private(仅本类可访问)四种修饰符控制类和成员的可见性,核心区别在于访问范围:public > protected > 默认 > private。

package com.example;

public class AccessModifiersExample {
    public int publicVar = 1;       // 所有类可见
    protected int protectedVar = 2; // 同包类+子类可见
    int defaultVar = 3;             // 同包类可见(无修饰符)
    private int privateVar = 4;     // 仅本类可见

    public void accessCheck() {
        System.out.println(privateVar); // 本类内可访问所有成员
    }
}

// 同包类测试
class SamePackageTester {
    void test() {
        AccessModifiersExample obj = new AccessModifiersExample();
        System.out.println(obj.publicVar);     // ✓ 可访问
        System.out.println(obj.protectedVar);  // ✓ 可访问
        System.out.println(obj.defaultVar);    // ✓ 可访问
        // System.out.println(obj.privateVar); // ✗ 编译错误
    }
}

// 不同包子类测试
package other;
import com.example.AccessModifiersExample;

class SubClass extends AccessModifiersExample {
    void test() {
        System.out.println(publicVar);     // ✓ 可访问
        System.out.println(protectedVar);  // ✓ 可访问(子类权限)
        // System.out.println(defaultVar);  // ✗ 编译错误(非同包)
        // System.out.println(privateVar);  // ✗ 编译错误
    }
}

// 无关类测试
package other;
import com.example.AccessModifiersExample;

class UnrelatedClass {
    void test() {
        AccessModifiersExample obj = new AccessModifiersExample();
        System.out.println(obj.publicVar);    // ✓ 可访问
        // System.out.println(obj.protectedVar); // ✗ 编译错误(非同包非子类)
        // System.out.println(obj.defaultVar);   // ✗ 编译错误
        // System.out.println(obj.privateVar);   // ✗ 编译错误
    }
}

12. 面向对象和面向过程区别、面向对象的三大特征

面向过程以步骤为中心(如C语言),将问题分解为线性流程,直接操作数据;面向对象(如Java)以对象为中心,将数据和方法封装成独立实体,通过对象交互解决问题,更符合现实世界模型。

面向对象三大特征:

封装:隐藏对象内部细节(如private变量),通过公共方法(getter/setter)安全访问

继承:子类复用父类特性(如class Dog extends Animal),实现代码复用和层次关系

多态:同一操作对不同对象有不同行为(如父类引用指向子类对象Animal a = new Dog(); a.sound()),提高扩展性

// 封装:隐藏细节,暴露接口
class BankAccount {
    private double balance;  // 私有属性封装
    
    public void deposit(double amount) {  // 公共方法操作数据
        if (amount > 0) balance += amount;
    }
}

// 继承:子类复用父类功能
class Animal {  // 父类
    void makeSound() { System.out.println("Some sound"); }
}
class Dog extends Animal {  // 继承
    @Override void makeSound() { System.out.println("Bark!"); }
}

// 多态:同一接口不同实现
public class Main {
    public static void main(String[] args) {
        Animal animal1 = new Dog();    // 父类引用指向子类对象
        Animal animal2 = new Cat();     // 另一个子类对象
        
        animal1.makeSound();  // 输出"Bark!" (动态绑定)
        animal2.makeSound();  // 输出"Meow!" (多态行为)
    }
}

13.重载和重写的区别

重载是在同一类中定义方法名相同但参数不同(类型/数量/顺序)的方法,用于扩展功能(如print(int)和print(String)),编译时确定调用;
重写是子类覆盖父类方法,要求方法名、参数、返回类型完全相同,用于实现多态(如子类重写Animal.sound()),运行时动态绑定。

class Animal {
    // 可被重写的方法
    public void makeSound() {
        System.out.println("Animal makes sound");
    }
    
    // 重载示例:参数数量不同
    public void eat() {
        System.out.println("Animal eats");
    }
    public void eat(String food) {  // 重载eat()
        System.out.println("Animal eats " + food);
    }
}

class Dog extends Animal {
    // 重写父类方法 (方法签名完全相同)
    @Override
    public void makeSound() {
        System.out.println("Dog barks: Woof!");
    }
    
    // 重载示例:参数类型不同
    public void fetch() {
        System.out.println("Dog fetches stick");
    }
    public void fetch(String item) {  // 重载fetch()
        System.out.println("Dog fetches " + item);
    }
}

public class Main {
    public static void main(String[] args) {
        // 重载演示
        Dog dog = new Dog();
        dog.eat();          // 调用Animal.eat()
        dog.eat("bone");    // 调用Animal.eat(String) - 重载
        
        dog.fetch();        // 调用Dog.fetch()
        dog.fetch("ball");  // 调用Dog.fetch(String) - 重载
        
        // 重写演示 (多态)
        Animal animal = new Dog();
        animal.makeSound(); // 运行时绑定Dog.makeSound() - 输出"Woof!"
    }
}

14.序列化和反序列化是什么

序列化是将对象转换为字节流的过程(保存游戏存档、微服务通信、缓存),
反序列化是将字节流恢复为对象的过程(读取配置文件、接收网络数据)
本质是对象状态的持久化和重建,与编程语言无关。

import java.io.*;

// 必须实现Serializable接口(标记接口)
class User implements Serializable {
    private static final long serialVersionUID = 1L; // 版本控制
    private String name;
    private transient int age; // transient字段不被序列化

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return name + " (" + age + " years)";
    }
}

public class SerializationDemo {
    public static void main(String[] args) {
        User user = new User("Alice", 30);
        
        // === 序列化 ===
        try (ObjectOutputStream oos = new ObjectOutputStream(
                new FileOutputStream("user.data"))) {
            
            oos.writeObject(user); // 对象→字节流
            System.out.println("序列化完成: " + user);
            
        } catch (IOException e) {
            e.printStackTrace();
        }

        // === 反序列化 ===
        try (ObjectInputStream ois = new ObjectInputStream(
                new FileInputStream("user.data"))) {
            
            User restoredUser = (User) ois.readObject(); // 字节流→对象
            System.out.println("反序列化结果: " + restoredUser);
            
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

15.什么是泛型,有什么作用,泛型擦除是什么

泛型(Generics) 是Java的类型参数化机制(如List),核心作用是:

  • 类型安全(编译时检测类型错误)

  • 消除强制转换(自动处理类型转换)

  • 代码复用(一套逻辑处理多种类型)

泛型擦除是Java泛型的实现机制:编译器移除泛型类型信息(运行时不可见),保证兼容性但导致无法获取运行时泛型类型等限制。

import java.util.*;

public class GenericsDemo {
    // 泛型方法(类型安全 + 消除转换)
    public static <T> void printArray(T[] array) {
        for (T item : array) {
            System.out.print(item + " "); // 无需强制转换
        }
        System.out.println();
    }

    public static void main(String[] args) {
        // 1. 类型安全集合
        List<String> names = new ArrayList<>();
        names.add("Alice");
        names.add("Bob");
        // names.add(123);  // 编译错误:类型安全保护
        
        // 2. 泛型方法调用
        Integer[] ints = {1, 2, 3};
        String[] strs = {"Hello", "Generics"};
        printArray(ints);  // 输出: 1 2 3 
        printArray(strs);  // 输出: Hello Generics 

        // 3. 泛型擦除验证
        List<Integer> intList = new ArrayList<>();
        List<String> strList = new ArrayList<>();
        System.out.println("运行时类型相同? " + 
            (intList.getClass() == strList.getClass())); // 输出: true
    }
}

16. 什么是反射

反射是Java在运行时动态获取类信息(类名、方法、字段等)并操作对象的能力,它打破了"编译时确定"的限制,允许程序在运行时自省和修改行为。核心是通过Class对象获取元数据,实现:类动态加载、方法动态调用、字段动态访问、绕过访问限制等高级功能。

import java.lang.reflect.*;

public class ReflectionDemo {
    public static void main(String[] args) throws Exception {
        // 1. 获取类的Class对象(三种方式)
        Class<?> clazz = Class.forName("java.util.Date");
        // Class<?> clazz = Date.class;
        // Class<?> clazz = new Date().getClass();
        
        // 2. 动态创建对象(相当于 new Date())
        Object date = clazz.getConstructor().newInstance();
        System.out.println("创建对象: " + date);
        
        // 3. 动态调用方法(相当于 date.getTime())
        Method getTime = clazz.getMethod("getTime");
        long timestamp = (long) getTime.invoke(date);
        System.out.println("时间戳: " + timestamp);
        
        // 4. 访问私有字段(演示突破封装)
        Class<?> userClass = Class.forName("User");
        Object user = userClass.getConstructor(String.class).newInstance("Alice");
        
        Field nameField = userClass.getDeclaredField("name");
        nameField.setAccessible(true); // 关键:解除private限制
        System.out.println("反射获取私有字段: " + nameField.get(user));
        
        // 5. 修改私有字段
        nameField.set(user, "Bob");
        System.out.println("修改后字段值: " + nameField.get(user));
    }
}

// 辅助类
class User {
    private String name;
    
    public User(String name) {
        this.name = name;
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值