1、反射机制概述
1.1、反射机制有什么用?
通过Java语言中的反射机制可以操作字节码文件(class文件)。
1.2、反射机制相关的类在哪个包下?
反射机制在java.lang.reflect.*包下。
1.3、反射机制相关的重要的类有哪些?
java.lang.class:代表整个字节码,代表一个类型。
java.lang.reflect.Method:代表字节码中的方法字节码。
java.lang.reflect.Constructor:代表字节码中的构造方法字节码。
java.lang.reflect.Field:代表字节码中的属性字节码。
2、获取Class的三种方式
/*
第一种:Class c =Class.forName("完整类带包名");
第二种:Class c = 对象.getClass();
第三种:java语言任何一种类型,包括基本数据类型,它都有.class属性。
*/
package com.wcs.reflect;
import java.util.Date;
/**
* 使用反射获取类的三种方式
*/
public class ReflectTest01 {
public static void main(String[] args) {
/*
Class.forName()
静态方法
方法的参数是一个字符串
字符串需要的是一个完整类名
完整类名必须带有包名。java.lang包也不能省略。
*/
Class c1 = null;
try {
c1 = Class.forName("java.lang.String");//代表String.class文件
Class c2 = Class.forName("java.util.Date");//代表Date类型
Class c3 = Class.forName("java.lang.Integer");//代表Integer类型
Class c4 = Class.forName("java.lang.System");//代表System类型
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//Java中任何一个对象都有一个方法:getClass()
String s = "abc";
Class x = s.getClass();//x代表String.class字节码文件,x代表String类型
System.out.println(x == c1);//true (==判断的是对象的内存地址)
//第三种方式
Class z = String.class;
Class k = Date.class;
Class f = int.class;
Class e = double.class;
System.out.println(x == z);//true
}
}
3、反编译Field
package com.wcs.field;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/**
* 反编译
* 获取类的属性
*/
public class ReflectTest03 {
public static void main(String[] args) {
try {
//获取整个类
Class studentClass = Class.forName("com.wcs.field.Student");
//完整类名 com.wcs.field.Student
String className = studentClass.getName();
System.out.println(className);
//简单类名 Student
String simpleName = studentClass.getSimpleName();
System.out.println(simpleName);
//获取类中所有的public修饰的Field
Field[] fields = studentClass.getFields();
System.out.println(fields.length);//1
//取出这个Filed
Field f = fields[0];
String fName = f.getName();
System.out.println(fName);//no
//获取所有的Filed
Field[] fs = studentClass.getDeclaredFields();
System.out.println(fs.length);//4
//遍历fs
for (Field field : fs) {
System.out.println("=========");
//获取属性的修饰符列表
int i = field.getModifiers();
System.out.println(i);//返回的是一个数字,每个数字是修饰符的代号
//把数字转换成字符串
String s = Modifier.toString(i);
System.out.println(s);
//获取属性的类型
Class fType = field.getType();
String typeName = fType.getName();
System.out.println(typeName);
//获取属性的名字
System.out.println(field.getName());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
4、通过反射机制访问对象属性
package com.wcs.field;
import java.lang.reflect.Field;
/**
* 怎么通过反射机制访问一个Java对象的属性?
* 给属性赋值set
* 获取属性值get
*/
public class ReflectTest04 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
//不使用反射机制,怎么访问一个对象的属性?
Student s = new Student();
//给属性赋值
s.no = 1111;
//读取属性值
System.out.println(s.no);
//使用反射机制,怎么去访问一个对象的属性
Class studentClass = Class.forName("com.wcs.field.Student");
//obj就是一个Student对象,底层调用无参构造方法
Object obj = studentClass.newInstance();
//获取no属性
Field noFiled = studentClass.getDeclaredField("no");
//给no属性赋值2222
noFiled.set(obj, 2222);
/*
反射机制虽然让代码变得复杂了,但是为了“灵活”,也是值得的。
*/
//读取属性的值
System.out.println(noFiled.get(obj));
//可以访问私有的属性吗?
Field nameField = studentClass.getDeclaredField("age");
//打破封装(不安全)
// nameField.setAccessible(true);//这样在外部也是可以访问的
nameField.set(obj, 18);
System.out.println(nameField.get(obj));//无法访问私有属性
}
}
5、反编译Method
package com.wcs.method;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* 反射Method
*/
public class ReflectTest05 {
public static void main(String[] args) throws ClassNotFoundException {
//获取类
Class studentClass = Class.forName("com.wcs.method.StudentSystem");
//获取所有的Method (包括私有的)
Method[] methods = studentClass.getDeclaredMethods();
//遍历methods
for (Method method : methods) {
//获取修饰符列表
System.out.println(Modifier.toString(method.getModifiers()));
//获取返回值类型
System.out.println(method.getReturnType());
//获取方法名
System.out.println(method.getName());
//获取方法的参数类型列表
Class[] parameterTypes = method.getParameterTypes();
for (Class parameterType : parameterTypes) {
System.out.println(parameterType.getSimpleName());
}
}
}
}
6、反射机制调用方法
package com.wcs.method;
import java.lang.reflect.Method;
/**
* 通过反射机制调用一个对象的方法
*/
public class ReflectTest06 {
public static void main(String[] args) throws Exception {
//不使用反射机制
StudentSystem studentSystem = new StudentSystem();
studentSystem.login("admin", "123");
//使用反射机制来调用一个对象的方法
Class stuClass = Class.forName("com.wcs.method.StudentSystem");
//创建对象
Object obj = stuClass.newInstance();
//获取method
Method loginMethod = stuClass.getDeclaredMethod("login", String.class, String.class);
//调用方法
System.out.println(loginMethod.invoke(obj, "admin", "123"));//true
}
}
7、反射调用构造方法
package com.wcs.constructor;
import java.lang.reflect.Constructor;
/**
* 通过反射调用构造方法
*/
public class ReflectTest07 {
public static void main(String[] args) throws Exception {
//不使用反射机制
Vip v1 = new Vip();
Vip v2 = new Vip(1001, "jack", true);
System.out.println(v1);
System.out.println(v2);
//使用反射机制,调用无参构造方法
Class vipClass = Class.forName("com.wcs.constructor.Vip");
Object obj = vipClass.newInstance();
//调用有参构造方法
//获取有参构造方法
Constructor con = vipClass.getDeclaredConstructor(int.class, String.class, boolean.class);
//调用有参构造方法new对象
Object newObj1 = con.newInstance(1002, "rose", false);
System.out.println(newObj1);
//获取无参构造方法
Constructor con2 = vipClass.getDeclaredConstructor();
//使用无参构造new对象
Object newObj2 = con2.newInstance();
System.out.println(newObj2);
}
}
8、获取父类和父接口
package com.wcs.superIn;
/**
* 通过反射获取父类和父接口
*/
public class ReflectTest08 {
public static void main(String[] args) throws ClassNotFoundException {
//String举例
Class stringClass = Class.forName("java.lang.String");
//获取String的父类
Class superclass = stringClass.getSuperclass();
System.out.println(superclass);
//获取String类实现的所有接口
Class[] interfaces = stringClass.getInterfaces();
for (Class anInterface : interfaces) {
System.out.println(anInterface);
}
}
}