1、反射机制有什么用?
通过java语言中的反射机制可以操作字节码文件(可以读和修改字节码文件。)
通过反射机制可以操作代码片段。(class文件。)
2、反射机制相关的重要的类有哪些?
类 | 含义 |
java.lang.Class | 代表整个字节码。代表一个类型,代表整个类。 |
java.lang.reflect.Method | 代表字节码中的方法字节码。代表类中的方法。 |
java.lang.reflect.Constructor | 代表字节码中的构造方法字节码。代表类中的构造方法。 |
java.lang.reflect.Field | 代表字节码中的属性字节码。代表类中的成员变量(静态变量+实例变量)。 |
注:必须先获得Class才能获取Method、Constructor、Field。
3.获取Class的三方式
public class Demo06 {
/**
* 获取class对象
* @param args
*/
public static void main(String[] args) throws ClassNotFoundException {
/**
* 方式1:直接通过类名.class获取(最常用的方法)
*/
Class<Person> personClass = Person.class;
System.out.println(personClass); //class com.zxb.test10.Person
/**
* 方式2: 通过Class.forName(路径)的方式获取(比较灵活,可以传递不同的路径,获取不同的class对象)
*/
String path = "com.zxb.test10.Person";
Class<?> aClass = Class.forName(path);
System.out.println(aClass); //class com.zxb.test10.Person
/**
* 这种方式比较好少用
*/
Class<? extends Person> aClass1 = new Person().getClass();
System.out.println(aClass1); //class com.zxb.test10.Person
}
}
5、通过反射实例化对象
package com.zxb.web.test01Lx;
public class Student {
private String name;
private Integer age;
public String sex="男";
public String character;
public Student() {
}
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public void me(){
System.out.println("我是私有方法");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
", character='" + character + '\'' +
'}';
}
}
public class Test {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException,
InstantiationException, NoSuchMethodException, NoSuchFieldException, InvocationTargetException {
/**
* 通过反射机制调用构造方法实例化java对象
*/
/**
* 方式1:使用newInstance()方法,调用无参构造方法
*/
Class<Student> sc1 = Student.class;
Object object1 = sc1.newInstance();
/**
* 方式2:调用有参构造方法
*/
Class<Student> sc2 = Student.class;
//获取到这个有参数的构造方法,里面传参数的类型
Constructor<Student> declaredConstructor = sc2.getDeclaredConstructor(String.class, Integer.class);
//创建有参构造对象
Object object2 = declaredConstructor.newInstance("蛮族之王", 28);
System.out.println(object2); //Student{name='蛮族之王', age=28, sex='男', character='null'}
/**
* 方式3:调用无参构造方法
*/
Class<Student> sc3 = Student.class;
//获取到这个无参数的构造方法,不用传参数的类型
Constructor<Student> declaredConstructor1 = sc3.getDeclaredConstructor();
Object object3 = declaredConstructor1.newInstance();
System.out.println(object3); //Student{name='null', age=null, sex='男', character='null'}
//给对象赋值
((Student) object3).setName("你好呀");
System.out.println(object3); //Student{name='你好呀', age=null, sex='男', character='null'}
}
5、JDBC重点(Class.forName导致类加载)
如果你只是希望一个类的静态代码块执行,其它代码一律不执行,可以使用:
Class.forName("完整类名");
这个方法的执行会导致类加载,类加载时,静态代码块执行。
6、反射Filed【反射一个类的属性】
6.1 获取类中所有public修饰的属性
public class Test {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException,
InstantiationException, NoSuchMethodException, NoSuchFieldException, InvocationTargetException {
Class<?> ac = Class.forName("com.zxb.web.test01Lx.Student");
/**
* 获取类中所有public修饰的属性
*/
Field[] fields = ac.getFields();
for (Field i : fields) {
System.out.println(i.getName());
}
/**
* 获取类中所有私有的属性
*/
Field[] fields1 = ac.getDeclaredFields();
for (Field i : fields1) {
System.out.println("=========================================");
// 获取属性的修饰符列表,返回的修饰符是一个数字,每个数字是修饰符的代号
// 用Modifier类的toString转换成字符串
System.out.println(Modifier.toString(i.getModifiers())); //private
System.out.println(i.getType().getSimpleName());// 获取属性的类型 String
System.out.println(i.getName());// 获取属性的名字 name
}
}
6.2 获取类中所有的实例方法
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException,
InstantiationException, NoSuchMethodException, NoSuchFieldException, InvocationTargetException {
Class<?> ac = Class.forName("com.zxb.web.test01Lx.Student");
/**
* 获取类中所有私有的属性
*/
Field[] fields1 = ac.getDeclaredFields();
for (Field i : fields1) {
System.out.println("=========================================");
// 获取属性的修饰符列表,返回的修饰符是一个数字,每个数字是修饰符的代号
// 用Modifier类的toString转换成字符串
System.out.println(Modifier.toString(i.getModifiers())); //private
System.out.println(i.getType().getSimpleName());// 获取属性的类型 String
System.out.println(i.getName());// 获取属性的名字 name
}
}
6.3 public修饰的属性,给属性设置值 set()、get()
/**
* 通过反射操作public修饰的属性,给属性设置值*
* set()
* get()
*/
Object obj1 = ac.newInstance();
Field getFid = ac.getDeclaredField("character");
getFid.set(obj1,"张三丰");
System.out.println(getFid.get(obj1)); //张三丰
6.4 setAccessible打破封装,给私有属性赋值
/**
* setAccessible打破封装,给私有属性赋值
*/
Class<Student> sc = Student.class;
Object object = sc.newInstance();
Field name = sc.getDeclaredField("name");
//打破封装
name.setAccessible(true);
name.set(object, "张三");
System.out.println(name.get(object)); //张三
7. Class类方法
7.1 getMethods获取类中public修饰的方法
Method[] methods = ac.getMethods();
for (Method i:methods) {
System.out.println(i.getName());
}
7.2 getDeclaredMethods获取类中所有的实例方法
Method[] methods1 = ac.getDeclaredMethods();
for (Method i : methods1) {
System.out.println(i.getName());
}
7.3 通过反射调用public修饰的方法
public static void main(String[] args) {
/**
* 通过反射调用public修饰的方法
*/
Class<?> studentClass = Student.class;
//实例化一个对象
Object o = studentClass.newInstance();
//通过getMethod方法取得setName这个方法的实例化对象,方法名称与参数类型(String.class)
Method setName = studentClass.getMethod("setName", String.class);
//调用invoke方法,调用setName方法。invoke方法中需要你指定给那个对象的那个方法进行传参
setName.invoke(o,"娜美");
//通过getMethod方法取得getName这个方法的实例化对象,方法名称与参数类型,如果没有参数可以不用传参数类型
Method getName = studentClass.getMethod("getName");
//调用invoke方法,调用getName方法
Object result = getName.invoke(o);
System.out.println(result); // 娜美
}
7.4 通过反射机制调用构造方法实例化java对象
public static void main(String[] args) {
/**
* 方式1:使用newInstance()方法,调用无参构造方法
*/
Class<Student> sc1 = Student.class;
Object object1 = sc1.newInstance();
/**
* 方式2:调用有参构造方法
*/
Class<Student> sc2 = Student.class;
//获取到这个有参数的构造方法,里面传参数的类型
Constructor<Student> declaredConstructor = sc2.getDeclaredConstructor(String.class, Integer.class);
//创建有参构造对象
Object object2 = declaredConstructor.newInstance("蛮族之王", 28);
System.out.println(object2); //Student{name='蛮族之王', age=28, sex='男', character='null'}
/**
* 方式3:调用无参构造方法
*/
Class<Student> sc3 = Student.class;
//获取到这个无参数的构造方法,不用传参数的类型
Constructor<Student> declaredConstructor1 = sc3.getDeclaredConstructor();
Object object3 = declaredConstructor1.newInstance();
System.out.println(object3); //Student{name='null', age=null, sex='男', character='null'}
//给对象赋值
((Student) object3).setName("你好呀");
System.out.println(object3); //Student{name='你好呀', age=null, sex='男', character='null'}
}
8. 获取一个类的父类以及实现的接口
public static void main(String[] args) {
/**
* 获取一个类的父类以及实现的接口
* 重点:给你一个类,怎么获取这个类的父类,已经实现了哪些接口?
* 以String举例
*/
//获取String的反射对象
Class<String> sc4 = String.class;
//获取String类的父类
Class<? super String> sc5 = sc4.getSuperclass();
System.out.println(sc5); //class java.lang.Object
//获取String类实现的所有接口
Class<?>[] interfaces = sc4.getInterfaces();
System.out.println(Arrays.toString(interfaces)); //[interface java.io.Serializable, interface java.lang.Comparable, interface java.lang.CharSequence]
for (Class i:interfaces) {
System.out.println(i.getName()); //java.io.Serializable、java.lang.Comparable、java.lang.CharSequence
}
}
}