反射
1. 反射取构造方法并使用
-
Constructor<?> [] getConstructors():返回所有公共构造方法对象的数组
-
Constructor<?> [] getDeclaredConstructors(): 返回所有构造方法对象的数组
-
Constructor< T> getConstructor(Class<?>… parameterTypes):返回单个公共构造方法对象
-
Constructor< T> getDeclaredConstructor(Class<?>…parameterTypes):返回单个构造方法对象
Constructor类中用于创建对象的方法:
- newInstance: 根据指定的构造方法创建对象
暴力反射:也要会
案例:
package Lambda;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
//测试类
public class Demo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//获取Class对象
Class<?> c = Class.forName("student.Student");
//显示构造方法
Constructor<?>[] declaredConstructors = c.getDeclaredConstructors();
for (Constructor con : declaredConstructors) {
System.out.println(con);
}
//public student.Student()
//public student.Student(java.lang.String,int,java.lang.String)
System.out.println("----------------");
Constructor<?> constructor = c.getConstructor();
Object obj = constructor.newInstance();//创建对象
System.out.println(obj);
//Student{name='null', age=0, school='null'}
}
}
案例:获取有参构造方法
package Lambda;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
//测试类
public class Demo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//获取Class对象
Class<?> c = Class.forName("student.Student");
Constructor<?> con = c.getConstructor(String.class, int.class, String.class);//基本数据类型也可以通过.class 获取对应的class对象
Object obj = con.newInstance("wen", 20, "常州");
System.out.println(obj);
}
}
案例:暴力反射, (获取私有)
package Lambda;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
//测试类
public class Demo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//获取Class对象
Class<?> c = Class.forName("student.Student");
Constructor<?> con = c.getDeclaredConstructor(String.class);
//暴力反射
con.setAccessible(true);//取消访问检查
Object obj = con.newInstance("wen");
System.out.println(obj);
//Student{name='wen', age=0, school='null'}
}
}
2. 反射获取成员变量并使用
- Field[] getFields() : 返回所有公共成员变量对象的数组
- Field[] getDeclaredFields() : 返回所有成员变量对象的数组
- Field getField(String name):返回单个公共成员变量对象
- Field getDeclaredField(String name):返回单个成员变量对象
package Lambda;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
//测试类
public class Demo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
//Class对象
Class<?> c = Class.forName("student.Student");
//得到所有的成员变量
Field[] fields = c.getDeclaredFields();
for (Field filed :
fields) {
System.out.println(filed);
//private java.lang.String student.Student.name
//int student.Student.age
//public java.lang.String student.Student.school
}
System.out.println("----------------------");
//得到特定的成员变量
Field nameFiled = c.getDeclaredField("name");
System.out.println(nameFiled);
//private java.lang.String student.Student.name
}
}
案例练习:用到暴力反射
package student;
/* 学生类
alt+insert 卧槽无敌的快捷键!!!
*/
public class Student {
private String name;
int age;
public String school;
public Student() {
}
public Student(String name) {
this.name = name;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student(String name, int age, String school) {
this.name = name;
this.age = age;
this.school = school;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSchool() {
return school;
}
public void setSchool(String school) {
this.school = school;
}
public void show() {
System.out.println("????");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school='" + school + '\'' +
'}';
}
}
package Lambda;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
//测试类
public class Demo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
//Class对象
Class<?> c = Class.forName("student.Student");
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
//赋值
Field name = c.getDeclaredField("name");
name.setAccessible(true);//IllegalAccessException 的 报错解决方案:暴力反射
name.set(obj, "wts");
Field age = c.getDeclaredField("age");
age.setAccessible(true);//
age.set(obj, 20);
Field school = c.getDeclaredField("school");
school.set(obj, "cczu");
System.out.println(obj);
}
}
3. 反射获取成员方法
Class类中用于获取成员变量的方法:
- Method [] getMethods():返回所有公共成员方法对象的数组,包括继承的
- Method [] getDeclaredMethods():返回所有成员方法对象的数组,不包括继承的
- Method getMethod(String name, Class<?>… parameterTypes):返回单个公共成员方法对象
- Method getDeclaredMethod(String name,Class<?>… parameterTypes):返回单个成员方法对象
Method类中用于调用成员方法的方法:
.Object invoke(Object obj, Object…args):调用obj对象的成员方法,参数是args,返回值是Object类型
package Lambda;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//测试类
public class Demo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
//Class对象
Class<?> c = Class.forName("student.Student");
//返回所有公共成员发放对象的数组,包括继承
Method[] methods = c.getMethods();
for (Method method :
methods) {
System.out.println(method);
}
System.out.println("-----------------------");
//不包括继承
Method[] declaredMethods = c.getDeclaredMethods();
for (Method method :
declaredMethods) {
System.out.println(method);
}
System.out.println("-----------------------");
//方法调用
//创建对象
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
Method m1 = c.getDeclaredMethod("method1");
m1.invoke(obj);//method1
}
}
案例:
package student;
/* 学生类
alt+insert 卧槽无敌的快捷键!!!
*/
public class Student {
private String name;
int age;
public String school;
public Student() {
}
public Student(String name) {
this.name = name;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student(String name, int age, String school) {
this.name = name;
this.age = age;
this.school = school;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSchool() {
return school;
}
public void setSchool(String school) {
this.school = school;
}
public void show() {
System.out.println("????");
}
public void method1() {
System.out.println("method1");
}
public void method2(String s) {
System.out.println(s);
}
public String method3(String name, int age) {
return name + "," + age;
}
private void function() {
System.out.println("function");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school='" + school + '\'' +
'}';
}
}
package Lambda;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//测试类
public class Demo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
//创建对象
Class<?> c = Class.forName("student.Student");
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
//调用method1
Method m1 = c.getDeclaredMethod("method1");
m1.invoke(obj);//method1
//调用method2 有形参
Method m2 = c.getDeclaredMethod("method2", String.class);
m2.invoke(obj, "wts");//wts
//调用method3 返回值是String类型
Method m3 = c.getDeclaredMethod("method3", String.class, int.class);
Object m3Invoke = m3.invoke(obj, "wts", 20);
System.out.println(m3Invoke);//wts,20
//调用私有方法 function
Method fun1 = c.getDeclaredMethod("function");
fun1.setAccessible(true);//暴力
fun1.invoke(obj);//function
}
}
反射练习:向ArrayList< Integer >添加字符串
反射可以完成一些非同寻常的操作
package Lambda;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
//测试类
public class Demo {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//创建对象
ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.add(10);
Class<? extends ArrayList> arrayListClass = arrayList.getClass();
Method add1 = arrayListClass.getMethod("add", Object.class);
add1.invoke(arrayList, "hello");
System.out.println(arrayList);//[10, hello]
}
}
4. 通过配置文件运行类中的方法
反射的灵活性
package student;
/* 学生类 */
public class Student {
public void study() {
System.out.println("学生学习");
}
}
package student;
public class Teacher {
public void teach(){
System.out.println("老师教书");
}
}
配置文件txt:
className=student.Student
methodName=study
package Lambda;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
//测试类
public class Demo {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//加载数据
Properties prop = new Properties();
FileReader fileReader = new FileReader("Class.txt");
prop.load(fileReader);
fileReader.close();
String className = prop.getProperty("className");
String methodName = prop.getProperty("methodName");
//通过反射
Class<?> c = Class.forName(className);
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
Method method = c.getDeclaredMethod(methodName);
method.invoke(obj);
}
}
小结:加载数据不太熟练,反射很灵活,感觉像项目框架