1.反射
获取Class的类模板对象三种方法
每个类只有一个Class对象,无论用哪种方式获取,结果都是一样的
第一种方式
Class cls = Class.forName(“demo.Student”);
第二种方式
Class cls2 = Student.class;
第三种方式
Student stu = new Student();
Class cls3 = stu.getClass();
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
//第一种方式
Class cls = Class.forName("demo.Student");
System.out.println(cls.hashCode());
//第二种方式
Class cls2 = Student.class;
System.out.println(cls2.hashCode());
//第三种方式
Student stu = new Student();
Class cls3 = stu.getClass();
System.out.println(cls3.hashCode());
}
}
反射获取构造创建对象
import java.lang.reflect.Modifier;
public class Test2 {
public static void main(String[] args) {
Class cls = Student.class;
//获取修饰符
int i = cls.getModifiers();//获取类的修饰符的标志值
System.out.println(i);
String str = Modifier.toString(i);// 根据标记值找到对应的修饰符
System.out.println(str);
Package package1 = cls.getPackage();
System.out.println(package1);
//demo.Student 全限定名 包名+类名
String str2 = cls.getName();
System.out.println("获取类的全限定名"+str2);
System.out.println("获取类名:"+cls.getSimpleName());
System.out.println("类是否是接口"+cls.isInterface());
System.out.println("类是不是数组:"+cls.isArray());
System.out.println("类不是枚举:"+cls.isEnum());
}
}
所有的反射的起源是Class类
public class Student {
public String name;
protected int age;
String gender;
private double salary;
static String grade;
public Student() {
super();
}
public Student(String name, int age, String gender, double salary) {
super();
this.name = name;
this.age = age;
this.gender = gender;
this.salary = salary;
}
Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public void sleep() {
System.out.println("睡");
}
public void eat(String food) {
System.out.println("吃"+food);
}
public String work(String msg) {
System.out.println("工作");
return "完成";
}
public void play() {
System.out.println("玩游戏");
}
public static void drink() {
System.out.println("喝");
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", gender=" + gender + ", salary=" + salary + "]";
}
}
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Test3 {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
// 创建Student对象
try {
Class cls = Class.forName("demo.Student");
// 可以通过Class对象去 得到类中的所有的信息
// Constructor[] constructors = cls.getConstructors();// 只能得到 public修饰的
Constructor[] declaredConstructors = cls.getDeclaredConstructors();// 只要生命的都可以
for (Constructor constructor : declaredConstructors) {
System.out.println(constructor);
}
// 获取无参数的构造方法
Constructor constructor = cls.getDeclaredConstructor();
Constructor constructor2 = cls.getDeclaredConstructor(String.class, int.class);
// 有构造方法,就可以创建的对象了
Student obj = (Student) constructor.newInstance();
System.out.println(obj);
Student stu = (Student) constructor2.newInstance("zhangsan", 99);
System.out.println(stu);
// 特殊格式: 不需要使用constructor对象, 要求类中必须存在无参数的构造方法
Student stu2 = (Student) cls.newInstance();// 内部帮助调用的Student类的无参数的构造方法
System.out.println(stu2);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test4 {
public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// 获取Class对象
Class cls = Student.class;
// 获取的public修饰的方法
Method[] methods = cls.getMethods();// 得到本类和父类的public修饰的方法
/*for (Method method : methods) {
System.out.println(method);
}
*/
// 得到自己本类所有声明了的方法
Method[] declaredMethods = cls.getDeclaredMethods();
// 得到某一个方法parameter 参数
Method method = cls.getMethod("sleep");//method 代表的是sleep方法
// 创建对象才能调用非静态的方法
// 创建对象
Object stu = cls.newInstance();
// 调用sleep方法 无参数无返回值非静态
method.invoke(stu);// 调用方法
System.out.println("---------调用有参数无返回值非静态方法eat()-------------");
//1. 先获取eat方法的Method对象
Method eat = cls.getMethod("eat", String.class);
//2. 调用
eat.invoke(stu, "字符串");
System.out.println("---------调用有参数有返回值非静态方法work()-------------");
//1.先获取work方法的Method对象
Method work = cls.getMethod("work", String.class);
// invoke方法的返回值,其实就是调用的work方法的返回值
Object invoke = work.invoke(stu, "敲定码,bug虐我千百遍,我代bug如初恋");
System.out.println("work返回值:"+invoke);
System.out.println("---------调用私有的非静态方法play()-------------");
// 获取private 缺省 protected方法修饰的方法都要getDeclaredMethod
Method play = cls.getDeclaredMethod("play");// public void play();
play.setAccessible(true);// 可以访问其他类中私有的属性和方法
play.invoke(stu);
// 反射可能会破坏封装性.
System.out.println("---------调用静态方法drink()-------------");
Method drink = cls.getMethod("drink");
drink.invoke(null);// 静态方法不需要添加对象, 可以直接调用
}
}
2.反射调用属性
私有的属性正常只能本类使用, 如果使用反射调用其他类的私有属性需要设定访问权限
package demo;
import java.lang.reflect.Field;
public class Test5 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException {
//1. 获取Class对象
Class cls = Class.forName("demo.Student");
//2. 获取属性
Field[] fields = cls.getFields();// 只能获取到public修饰的属性
Field[] declaredFields = cls.getDeclaredFields();//获取自己声明的所有的属性
// 创建student对象
Student stu = (Student) cls.newInstance();
System.out.println("------获取public的name属性----------");
// 获取单个的属性
Field name = cls.getField("name");
// 设置属性值
name.set(stu, "zhangsansansans");
// 获取属性值
Object value = name.get(stu);
System.out.println(value);
System.out.println("------获取protected的age属性----------");
Field age = cls.getDeclaredField("age");
age.set(stu, 999);
Object value2 = age.get(stu);
System.out.println(value2);
System.out.println("------获取缺省的gender属性----------");
Field gender = cls.getDeclaredField("gender");
gender.set(stu, "男");
Object value3 = gender.get(stu);
System.out.println(value3);
System.out.println("------获取私有的salary属性----------");
Field salary = cls.getDeclaredField("salary");
// 私有的属性正常只能本类使用, 如果使用反射调用其他类的私有属性需要设定访问权限
salary.setAccessible(true);
salary.set(stu, 9999999999999.0);
Object value4 = salary.get(stu);
System.out.println(value4);
System.out.println("------获取静态的grade属性----------");
Field grade = cls.getDeclaredField("grade");
grade.set(null, "aaa");
Object object = grade.get(null);
System.out.println(object);
}
}