Java118 反射
反射
反射是将类中的属性,方法,构造方法等解剖成一个个小的对象,并且能够调用
什么意思?
怎么理解解剖?
为什么使用反射:
在一个类中,可以创建另外一个类的对象,调用其的属性和方法,无论那个类是否被创建了。//需要理解下
Integer
提供一个方法,可以调用类的属性 修正 可以获取类的属性、方法等
修正 反射提供一些方法 可以获取类的属性、方法等,获取到这些东西需要东西去接,接的东西就是解剖的哪些对象
返回的方法
创建对象
```java
public Student(String name, Integer age) {// 正确写法:直接使用参数赋值this.name = name; // 不是创建内部类,只是字段赋值this.age = age; // 使用传入的age参数,不是固定为2// 如果你真的想创建新的String对象(通常不需要)// this.name = new String(name);}
这么做有什么意义
```java
// 没有构造函数时,你需要这样创建对象:
Student s = new Student();
s.setName("张三"); // 分两步,可能忘记设置
s.setAge(20);// 有构造函数时,一步到位:
Student s = new Student("张三", 20); // 对象创建时就是完整的
public class Student {private String name;private Integer age;// 构造函数public Student(String name, Integer age) {// 正确写法:直接使用参数赋值this.name = name; // 不是创建内部类,只是字段赋值this.age = age; // 使用传入的age参数,不是固定为2// 如果你真的想创建新的String对象(通常不需要)// this.name = new String(name);}
}
怎么理解怎么理解字段赋值,一定要进行字段赋值吗
字段赋值就是给对象的属性(成员变量)设置初始值的过程。
public class Student {private String name; // 这是字段(成员变量)private Integer age; // 这也是字段public Student(String name, Integer age) {this.name = name; // 这是字段赋值:将参数name的值赋给字段namethis.age = age; // 这是字段赋值:将参数age的值赋给字段age}
}
一定要进行字段赋值吗?
不一定,但强烈推荐!这取决于你的需求:
情况1:必须赋值- 当字段没有默认值或默认值不合适时
public class Student {private String name; // 默认值 = nullprivate Integer age; // 默认值 = nullpublic Student(String name, Integer age) {// 如果不赋值,name和age都是null// this.name = name; // 如果注释掉,name保持null// this.age = age; // 如果注释掉,age保持null}public void printInfo() {System.out.println("姓名:" + name); // 可能输出"姓名:null"System.out.println("年龄:" + age); // 可能输出"年龄:null"}
}
Student student = new Student("张三", null);
// 如果不赋值,age就是null,使用时会报错:
// int realAge = student.getAge() + 1; // NullPointerException!
public class BankAccount {private String owner;private double balance;public BankAccount(String owner) {this.owner = owner; // 必须赋值this.balance = 0.0; // 必须赋值,明确初始余额为0}
}
情况2:可以不用赋值- 当默认值就符合需求时
java
public class Counter {private int count = 0; // 已经有默认值public Counter() {// 不需要赋值,count已经是0// 如果希望从0开始计数,就不需要再赋值}public Counter(int startFrom) {this.count = startFrom; // 需要赋值:覆盖默认值}
}
怎么在类里面实例化一个对象
public class School {// 1. 直接初始化成员变量private Classroom mainClassroom = new Classroom("高三(1)班");private static School instance = new School(); // 单例模式// 2. 声明但不初始化private Library library;private List<Teacher> teachers;// 3. 在构造函数中初始化public School() {this.library = new Library("学校图书馆");this.teachers = new ArrayList<>();// 添加一些初始老师this.teachers.add(new Teacher("张老师", "数学"));this.teachers.add(new Teacher("李老师", "语文"));}// 4. 在方法中创建对象public Student enrollNewStudent(String name, Integer age) {Student newStudent = new Student(name, age); // 实例化新学生mainClassroom.addStudent(newStudent);return newStudent;}public void organizeActivity(String activityName) {// 方法内临时对象Activity activity = new Activity(activityName, new Date());activity.execute();}// 5. 延迟初始化示例private Playground playground;public Playground getPlayground() {if (playground == null) {playground = new Playground("标准操场");}return playground;}
}
如何在类内定义属性
public class ClassName {// 1. 最基本的属性定义[访问修饰符] 数据类型 属性名;// 2. 带初始值的属性定义 [访问修饰符] 数据类型 属性名 = 初始值;// 3. 静态属性定义[访问修饰符] static 数据类型 属性名;
}
public class Student {// 定义属性 - 成员变量/字段private String name; // 私有属性,只能在类内部访问public Integer age; // 公有属性,任何地方都可以访问 protected String studentId; // 受保护属性,同包或子类可以访问String className; // 默认访问权限,同包内可以访问// 带初始值的属性private boolean graduated = false;private final String school = "某某大学"; // 常量,赋值后不能修改// 静态属性(类属性)public static int studentCount = 0;private static final String SCHOOL_CODE = "SCH001";// 引用类型的属性private Address address; // 自定义类对象private List<String> courses; // 集合对象
}
为什么不能直接拿到类内对象的属性?
public class BankAccount {private double balance; // 余额是敏感数据,不能直接修改// 如果balance是public,会出现这种情况:// BankAccount account = new BankAccount(1000);// account.balance = 1000000; // 黑客可以直接修改余额!// 正确的做法:通过方法控制访问public double getBalance() {return this.balance;}public void withdraw(double amount) {if (amount > 0 && amount <= balance) {balance -= amount;}}
}
问题3
public class student {private String name;public Integer times;
private Integer age;
private Integer fee;
student(String name,Integer age){this.name=name;
this.age=age;this.fee=2000;//如何理解通过get调用属性
}
//如何理解没有办法直接拿到类内对象的属性}
这里的构造方法是什么作用,可以不要这个构造方法吗
构造方法的作用:
对象初始化:创建Student对象时,自动执行构造方法中的代码
强制数据完整性:要求创建对象时必须提供name和age
设置初始状态:为对象的属性赋予初始值
如果没有构造方法会怎样?
java
// 如果没有构造方法,Java会提供默认无参构造方法
student s = new student(); // 可以这样创建,但所有属性都是默认值
// name = null, age = null, fee = null, times = null
结论:如果你希望对象创建时就具有合理的初始状态,就需要构造方法。
调用内部属性
通过get方法调用属性(封装的核心)
为什么要定义为private 定义为privite后 我初始化赋值 不是默认值吗?除了强制调用的,初始化变量强制需要赋值的属性,其他仍未null 或者特定值,不能隔离,这就是private 封装的含义吗?属性不能直接被外部访问是这个意思吗?如果我定义了Get方法,不就都能访问了吗?
public class student {private String name;public Integer times;private Integer age;private Integer fee;student(String name, Integer age){this.name = name;this.age = age;this.fee = 2000;}// 提供get方法让外部可以读取私有属性public String getName() {return this.name;}public Integer getAge() {return this.age;}public Integer getFee() {return this.fee;}// times是public,不需要get方法,但推荐也提供get方法保持一致性public Integer getTimes() {return this.times;}
}
试下Get方法


这里连get方法都没,name 和 age硬是调用不了
public class Main{public static void main(String[] args) {
student s=new student("name",5); //创建了一个实例//实例化了一个对象
s.times=14;System.out.println(s.times);System.out.println(s.getName());//为啥获得的是初始值?能获得新赋的值吗?System.out.println(s.getFee());}
}
答案是:getName()返回的就是你设置的值,不是"初始值",而是你构造时传入的值!
public class Main{public static void main(String[] args) {
student s=new student("xiaocao",5); //创建了一个实例//实例化了一个对象
s.times=14;System.out.println(s.times);System.out.println(s.getName());//为啥获得的是初始值?能获得新赋的值吗?System.out.println(s.getFee());}
}


还是得通过get方法才能调用private 属性的数值,不能直接调用。
问题4 格式化 格式 代码格式的快捷键是哪个
ctrl + alt + L
如何利用反射
每个类都有唯一的类对象,类对象可以得到类中的所有信息



Constructor<?> argConstructor = studentClass.getConstructor(String.class,Integer.TYPE);//这里的String.class Integer.Type是什么意思 为什么提示构造函数未找到
String.class:表示 String 类型的 Class 对象
Integer.TYPE:表示基本数据类型 int的 Class 对象(不是 Integer 包装类)
关键问题:Integer.TYPE对应的是 int,但您的 Student 类构造函数使用的是 Integer(包装类)!
getConstructor(String.class, Integer.TYPE) // 寻找:String + int 的构造函数
// 相当于寻找:Student(String name, int age)
// 将 Integer.TYPE 改为 Integer.class
Constructor<?> argConstructor = studentClass.getConstructor(String.class, Integer.class);
Java 中类型 Class 对象的区别


还是找不到


代码有点问题?
import java.lang.reflect.Constructor;public class ReflectionExample {public static void main(String[] args){try{Class<?> studentClass = Class.forName("student");System.out.println("成功加载student类");Constructor<?>[] allConstructors=studentClass.getConstructors();System.out.println("找到的构造函数是:");for (Constructor<?> con : allConstructors){System.out.println("" +con);}Constructor<?> noArgConstructor = studentClass.getConstructor();Constructor<?> argConstructor = studentClass.getConstructor(String.class,Integer.class);System.out.println("找到目标构造函数 " + argConstructor);//这里的String.class Integer.Type是什么意思Object student1=noArgConstructor.newInstance();Object student2=argConstructor.newInstance("好的",20);System.out.println("实例创建成功" +student2);System.out.println(student2);}catch (ClassNotFoundException e){System.out.println("类未找到"+e.getMessage());}catch (NoSuchMethodException e){System.out.println("构造函数未找到:"+e.getMessage());}catch (Exception e){e.printStackTrace();}}
}
public class student {//怎么实例化一个对象//怎么创建属性private String name;public Integer times;private Integer age;private Integer fee;student(String name, Integer age) {this.name = name;//是创建了一个内部类吗? 还是实例化了一个name =name//字段赋值 修正:字段赋值this.age = age;//底下是实例化了age=2//修正 都是字段赋值 如果不赋值 就默认为nullthis.fee = 2000;//如何理解通过get调用属性//如果是private方法 如果不用get方法,无法在其他类中找到调用该属性}
//如何理解没有办法直接拿到类内对象的属性 //修正 没有办法知道类内有什么样的属性//通过get去访问属性
//自动装箱 拆想需要了解下void student1(){}public Integer getTimes() {return times;}public String getName() {return name;}public Integer getFee() {return fee;}public Integer getAge() {return age;}//格式化 格式 代码格式的快捷键是哪个//ctrl + alt + L// Class<?> studentClass=Class.forName("student");//studentClass.getConstructor();//studentClass.getConstructor(String.class,Integer.Type);
//这个方法是要创建的吗?不是内部方法吗?
}
public class Main {public static void main(String[] args) {student s = new student("xiaocao", 5); //创建了一个实例//实例化了一个对象s.times = 14;System.out.println(s.times);System.out.println(s.getName());//为啥获得的是初始值?能获得新赋的值吗?System.out.println(s.getFee());
try {student sl = new student("llk",21);System.out.println("年龄类型" +(sl.getAge() instanceof Integer ? "Integer" :"int"));
} catch (Exception e) {System.out.println("创建失败"+e.getMessage());
}}
}