反射
一.反射的定义
1.反射是指程序运行中动态的获取类的信息,并访问,类的信息包含:属性和方法,构造方法
2.反射是通过JDK给我们提供一套API来获取类的属性,方法,构造方法并且可以使用
3.类的对象是Class
方法也是对象,属于Method类
构造方法也是对象,属于Constructor类
字段属性也是对象,Filed类
这些类都位于java.lang.reflect反射包中
二.反射调用类代码:
public class Test {
public static void main(String[] args) {
try {
Class<?> dateClass = Class.forName("java.util.Date");
System.out.println(dateClass);
Object newInstance = dateClass.newInstance();
System.out.println(newInstance);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
代码解释:
通过Class.forName方法获得的类名字和属于的包,传入Class修饰的对象中,可以直接输出,然后得到其包和类,然后通过其定义的对象dateClass调用newInstance方法可以得到一个对象,也可以直接输出,在此处直接输出代表输出Data类的对象,即直接输出未定义格式的时间。
三.通过反射获取类的无参构造方法
1.无参构造方法
public class Test1 {
public static void main(String[] args) {
// Person p1 = new Person();
try {
Class<?> personClass = Class.forName("com.qfedu.test6.Person");
Constructor<?> constructor = personClass.getConstructor();
Object newInstance = constructor.newInstance();
System.out.println(newInstance);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
class Person {
private String name;
private String address;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person() {
System.out.println("Person无参构造方法");
}
public Person(String name, String address, int age) {
this.name = name;
this.address = address;
this.age = age;
}
@Override
public String toString() {
System.out.println("Person toString方法");
return "Person [name=" + name + ", address=" + address + ", age=" + age + "]";
}
}
代码解释:
先用Class.forName获取类的信息,然后用Class定义的对象调用getConstructor()获取所有的构造方法赋值给constructor,然后用constructor调用newInstance方法获得类的对象,直接输出可以得到方法
2.有参构造方法
package com.qfedu.test6;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public class Test2 {
public static void main(String[] args) {
try {
Class<?> stuClass = Class.forName("com.qfedu.test6.Student");
Constructor<?> constructor = stuClass.getConstructor(String.class,String.class,int.class);
Object newInstance = constructor.newInstance("赵四","象牙山",20);
System.out.println(newInstance);
Constructor<?>[] constructors = stuClass.getConstructors();
for(Constructor<?> con : constructors) {
System.out.println(con.getParameterCount());
Parameter[] parameters = con.getParameters();
for(Parameter p : parameters) {
System.out.print("构造方法中参数的名称" + p.getName() + "\t");
System.out.println("构造方法中参数的名称" + p.getType());
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
class Student {
private String name;
private String address;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student() {
System.out.println("Student无参构造方法");
}
public Student(String name, String address, int age) {
this.name = name;
this.address = address;
this.age = age;
}
public Student(int age ,String name, String address) {
this.name = name;
this.address = address;
this.age = age;
}
@Override
public String toString() {
System.out.println("Student toString方法");
return "Student [name=" + name + ", address=" + address + ", age=" + age + "]";
}
}
代码解释:
forName先获取对应类的信息,然后getConstructor(String.class,String.class,int.class)获取所有构造方法的信息,当不传参数类型时为无参构造,然后用newInstance方法获得对象,并进行传值constructor.newInstance(“赵四”,“象牙山”,20),直接输出对象即可得到传入的参数
调用getConstructors()方法获得构造方法有几个参数,用增强for循环进行输出,getParameters()方法获取参数的具体信息,然后在增强for循环里使用对象调方法得到我们想要的属性用增强for循环进行循环,输出的时候用增强for定义的对象可以调出我们想要的参数信息,比如p.getName()得到参数的参数的名称,p.getType()获得参数的类型
3.使用反射调用方法
package com.qfedu.test6;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.GregorianCalendar;
public class Test3 {
public static void main(String[] args) {
try {
Class<?> gradeClass = Class.forName("com.qfedu.test6.Grade");
Object newInstance = gradeClass.newInstance();
Method[] methods = gradeClass.getMethods();
Method setNameMethod = null;
Method setStuCountMethod = null;
for(Method m : methods) {
System.out.println(m.getName());
if(m.getName().equals("setName")) {
setNameMethod = m;
}
if(m.getName().equals("setStuCount")) {
setStuCountMethod= m;
}
}
// newInstance.setName("三年二班")
setNameMethod.invoke(newInstance, "三年二班");
setStuCountMethod.invoke(newInstance, 30);
System.out.println(gradeClass.getMethod("getName").invoke(newInstance));
System.out.println(gradeClass.getMethod("getStuCount").invoke(newInstance));
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class Grade{
private String name;
private int stuCount;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getStuCount() {
return stuCount;
}
public void setStuCount(int stuCount) {
this.stuCount = stuCount;
}
public Grade() {
}
public Grade(String name, int stuCount) {
this.name = name;
this.stuCount = stuCount;
}
@Override
public String toString() {
return "Grade [name=" + name + ", stuCount=" + stuCount + "]";
}
}
先用forName获得类信息,用newInstance获得对象,再用getMethods获取所有方法,然后定义两个空白的方法setNameMethod和setStuCountMethod,然后用增强for循环遍历所有的方法,m.getName()可以获取所有方法,包括继承父类的,然后用if语句进行判断,遍历的方法中有没有我们想要的方法,有的话传值给我们之前定义的空白方法,然后通过invoke进行方法调用对象,格式为方法名.invoke(对象名,"传入的信息"),然后再输出时,通过我们获取到的类调用方法,再通过方法调用对象进行输出,格式为类.getMethod("我们要调用的方法").invoke(我们获得的对象)
四.通过反射调用对象
package com.qfedu.test6;
import java.lang.reflect.Field;
/**
* 调属性
* @author WHD
*
*/
public class Test4 {
public static void main(String[] args) {
try {
Class<?> schoolClass = Class.forName("com.qfedu.test6.School");
Object newInstance = schoolClass.newInstance();
Field[] fields = schoolClass.getFields();
Field nameField = null;
Field ageField = null;
for(Field f : fields) {
System.out.println(f.getName() + "\t" + f.getType());
if(f.getName().equals("name")) {
nameField = f;
}
if(f.getName().equals("age")) {
ageField = f;
}
}
// newInstance.name
nameField.set(newInstance, "赵四");
ageField.set(newInstance, 20);
System.out.println(schoolClass.getField("name").get(newInstance));
System.out.println(schoolClass.getField("age").get(newInstance));
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class School{
public String name;
public int age;
}
代码解释:
和调用方法一样,先forName获得类信息,newInstance获得对象,getFields获得所有字段信息,定义两个空白的字段,然后进行增强for循环遍历,在进行判断遍历里是否有我们想要的字段,有的话赋给我们定义的空白字段,通过字段使用set添加我们要添加的对象信息,格式为,字段.set(我们获得的对象,“需要传入的值”),输出的时候用我们获取的类信息调用getField调用字段,然后用get调用对像,具体格式为,类信息.getField(“我们要输出的字段名”).get(我们获得的对象)