反射获取class对象的三种方式
1、Class.forName(全类名)
2、类名.class
3、对象.getClass()
实现代码如下:
java
package com.itazhang.Demo1;
public class MyReflectDemo1 {
public static void main(String[] args) throws ClassNotFoundException {
//第一种获取class对象的方法
Class clazz1 = Class.forName("com.itazhang.Demo1.Student");
//第二种直接用对象去调用getClass
Student stu = new Student();
Class clazz2 = stu.getClass();
//第三种方法
Class clazz3 = Student.class;
}
}
反射获取构造方法
在利用class对象获取相关构造方法的步骤如下:先用Class.forname方法创建相应的class对象 ,再通过class对象调用相关的方法,有declared修饰的方法就能获取所有修饰符的构造方法,最后带s的是返回所有相关构造方法,而没有带s的只返回一个,例如:需要传递相应的类型参数得到相应参数的构造方法,如空参构造就不传递,两个的带参构造就传递这两个数据类型的字节码
Constructor constructor = clazz.getConstructor();
Constructor constructor1 = clazz.getConstructor(String.class, int.class);
java
package com.itazhang.Demo1;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class MyReflectDemo2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class clazz = Class.forName("com.itazhang.Demo1.Student");
//获取所有public修饰的构造方法
Constructor[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
System.out.println("----------------------------");
//获取所有修饰符的构造方法
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
System.out.println("------------------------------");
//获取单个public修饰的构造方法,传递相应的参数即可
Constructor constructor = clazz.getConstructor();
System.out.println(constructor);
//创建public修饰的构造方法的对象
Student stu1 = (Student) constructor.newInstance();
System.out.println(stu1);
System.out.println("-----------------1------------------");
Constructor constructor1 = clazz.getConstructor(String.class, int.class);
System.out.println(constructor1);
//获取单个所有修饰符的构造方法
Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class);
System.out.println(declaredConstructor);
//创建private修饰的对象
declaredConstructor.setAccessible(true);
Student stu =(Student) declaredConstructor.newInstance("张三");
System.out.println(stu);
}
}
获取了构造方法之后就能通过获取出来的对象调用newInstance方法创建相关构造方法的对象,但是要注意参数个数和类型得与构造方法中的一致,如下:这是一个public修饰的空参构造 ,所以创建出来的也是一个没有参数的对象
java
//获取单个public修饰的构造方法,传递相应的参数即可
Constructor constructor = clazz.getConstructor();
System.out.println(constructor);
//创建public修饰的构造方法的对象
Student stu1 = (Student) constructor.newInstance();
System.out.println(stu1);
而如果获取了private等私有修饰符的构造方法,如果需要用该构造方法,需要在创建对象之前使用setAccessible方法给此方法传递true,然后才能使用私有修饰符修饰的构造方法创建对象,如下:
java
//创建private修饰的对象
declaredConstructor.setAccessible(true);
Student stu =(Student) declaredConstructor.newInstance("张三");
System.out.println(stu);
利用反射获取成员变量
获取成员方法大致与获取构造方法相同,也是先创建相关类的Class对象,利用Class.forName获取class对象,如果想获取一个public修饰的成员变量就用getField方法,如果想获取其他修饰符的成员方法就用getDeclaredField方法,同样的如果想使用私有修饰符修饰的成员变量的话得调用setAccecible方法且传递true之后才能使用私有的成员方法,如下:
java
package com.itazhang.Demo2;
import java.lang.reflect.Field;
public class MyReflectDemo2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
Class clazz = Class.forName("com.itazhang.Demo2.Student");
//获取全部成员变量
Field[] fields = clazz.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("-----------1-----------");
//获取单个public修饰的成员变量
Field gender = clazz.getField("gender");
System.out.println(gender);
System.out.println("------------2---------");
//获取全部修饰符的成员变量
Field[] declaredFields = clazz.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
System.out.println("------------3-----------");
//获取单个所有修饰符的成员变量
Field age = clazz.getDeclaredField("age");
System.out.println(age);
System.out.println("------------4------------");
//使用private修饰符的成员变量
Student stu = new Student("azhang",22,"男");
age.setAccessible(true);
Object o = age.get(stu);
System.out.println(o);
}
}
反射获取成员方法
大致方法的使用与之前获取成员方法相同,但是如果要使用获取出的方法时,需要用获取出来的对象调用invoke方法,传入调用该获取出来方法的对象 ,和方法需要传递的参数,这样就能使用获取出的方法,代码如下:Student类中有一个private修饰的eat方法,该方法有一个返回值且是private修饰的方法,使用invoke方法会有一个返回值,该返回值就是使用的方法的返回值,如果没有返回值,默认返回null。
java
//获取方法
Student s = new Student();
Method eat = clazz.getDeclaredMethod("eat", String.class);
eat.setAccessible(true);
Object o1 = eat.invoke(s, "面条");
System.out.println(o1);
反射练习(一)
通过反射获取到两个不同类里的相关属性,且将这两个类对象的属性值写入到本地文件中
学生Student类
java
package com.itazhang.Demo3;
public class Student {
private String name;
private int age;
private String gender;
private String address;
public Student() {
}
public Student(String name, int age, String gender, String address) {
this.name = name;
this.age = age;
this.gender = gender;
this.address = address;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
/**
* 获取
* @return gender
*/
public String getGender() {
return gender;
}
/**
* 设置
* @param gender
*/
public void setGender(String gender) {
this.gender = gender;
}
/**
* 获取
* @return address
*/
public String getAddress() {
return address;
}
/**
* 设置
* @param address
*/
public void setAddress(String address) {
this.address = address;
}
public String toString() {
return "Student{name = " + name + ", age = " + age + ", gender = " + gender + ", address = " + address + "}";
}
}
老师Teacher类
java
package com.itazhang.Demo3;
public class Teacher {
private String name;
private int salary;
public Teacher() {
}
public Teacher(String name, int salary) {
this.name = name;
this.salary = salary;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return salary
*/
public int getSalary() {
return salary;
}
/**
* 设置
* @param salary
*/
public void setSalary(int salary) {
this.salary = salary;
}
public String toString() {
return "Teacher{name = " + name + ", salary = " + salary + "}";
}
}
反射代码执行类
java
package com.itazhang.Demo3;
import java.io.*;
import java.lang.reflect.Field;
public class MyReflectDemo3 {
public static void main(String[] args) throws IllegalAccessException, IOException {
Student stu = new Student("azhang",22,"男","chengdu");
Teacher tch = new Teacher("ahuai",12000);
saveObject(stu);
saveObject(tch);
}
public static void saveObject(Object obj) throws IllegalAccessException, IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\11Codingtext\\MyReflect\\a.txt",true));
Class clazz = obj.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
String name = field.getName();
Object value = field.get(obj);
System.out.println(name + "=" + value);
bw.write(name+"="+value);
bw.newLine();
bw.flush();
}
bw.close();
}
}
反射总结:
动态代理 (初始了解)
能实现无侵入式的给代码增加额外的功能。