欢迎光临
我们一直在努力

反射 定义、获取class对象的三种方式、获取构造方法、获取成员变量、获取成员方法(对应练习和笔记)

反射

1、反射的概述

反射定义

反射允许对封装的字段(成员变量),方法(成员方法)和构造函数(构造方法)的信息进行编程访问

  • 反射可以获取到类中的所有信息

  • 反射获取不是从java文件中获取的,而是从Class字节码文件中获取,所以需要先获取class对象

2、获取class对象的三种方式

获取class对象的三种方式

(1)Class.forName("全类名"); 在源代码阶段 (全类名指的是包名+类名,这里Class类中的方法)

(2)类名.class 在加载阶段

(3)对象.getClass(); 在运行阶段

package ReflectionClass;

public class MyClass1 {
public static void main(String[] args) throws ClassNotFoundException {
//1、第一种方式
//全类名:包名 + 类名
Class clazz = Class.forName("ReflectionClass.Student");
//打印该类的字节码文件
System.out.println(clazz);

//2、第二种方式
//一般更多当做参数使用
Class clazz2 = Student.class;
System.out.println(clazz2);

//3、第三种方式
Student s = new Student();
Class clazz3 = s.getClass();
System.out.println(clazz3);
}
}

3、反射获取构造方法

Constructor类就是构造方法
利用反射获取构造方法

(1)Class类中用于获取构造方法的方法

  • Construct<?>[] getConstructors(): 返回所有公共构造方法对象的数组
  • Construct<?>[] getDeclaredConstructors(): 返回所有构造方法对象的数组(包括私有构造)

注:这里和下面的Declared可以看做权限词,加上后可以获取包括private私有的所有构造方法

  • Construct<T> getConstructors(Class<?>…parameerTypes): 返回单个公共构造方法对象
  • Construct<T> getDeclaredConstructor(Class<?>…parameterTypes): 返回单个构造方法对象(包括私有构造,protected)

(2)Constructor类中用于创建对象的方法

T newInstance(Object…initargs): 根据指定的构造方法创建对象(Object类型,需要强转)

setAccessible(boolean flag): 设置为true,表示取消访问检查(如果要通过newInstance创建对象,如果构造方法是私有的,那就可以用该方法临时取消权限校验)也称为暴力反射

package ReflectionClass;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Parameter;

public class Myclass2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//1、获取class字节码文件
Class clazz = Class.forName("ReflectionClass.Student");
//2、获取所有的公共构造方法
Constructor[] cons = clazz.getConstructors();
for (Constructor c : cons) {
System.out.println(c);
}
//获取所有的构造方法(包括私有和protected)
Constructor[] con2 = clazz.getDeclaredConstructors();
for (Constructor c : con2) {
System.out.println(c);
}
//获取单个构造方法
Constructor con3 = clazz.getDeclaredConstructor();
System.out.println(con3);

Constructor con4 = clazz.getDeclaredConstructor(String.class);//String对应的字节码
System.out.println(con4);

Constructor con5 = clazz.getDeclaredConstructor(int.class);//int对应的字节码
System.out.println(con5);

Constructor con6 = clazz.getDeclaredConstructor(String.class, int.class);//String和int对应的字节码
/* System.out.println(con6);
int modifiers = con6.getModifiers();//获取构造方法的权限修饰符,只不过以整数形式返回
System.out.println("modifiers: " + modifiers);

Parameter[] parameters = con6.getParameters();
for (Parameter parameter : parameters) {
System.out.println("parameter: " + parameter);
}
*/
//暴力反射:表示临时取消权限校验
con6.setAccessible(true);
Student stu = (Student)con6.newInstance("张三",23);

System.out.println(stu);
}
}
public class Student {

private String name;
private int age;
private transient String address;

public Student() {}
public Student(String name) {
this.name = name;
}
protected Student(int age){
this.age = age;
}
private Student(String name,int age){
this.name = name;
this.age = age;
}

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;
}

@Override
public String toString() {
return "Student{" +
"name='" + name + '\\'' +
", age=" + age +
", address='" + address + '\\'' +
'}';
}
}

4、反射获取成员变量

Field就是成员变量
利用反射获取成员变量

(1)Class类中用于获取成员变量的方法

  • Field[] getFields(): 返回所有公共成员变量对象的数组
  • Field[] getDeclaredFields(): 返回所有成员变量对象的数组
  • Field getField(String name): 返回单个公共成员变量对象
  • Field getDeclaredField(String name): 返回单个成员变量对象
(2)Field类中用于创建对象的方法
  • void set(Object obj, Object value): 赋值
  • Object get(Object obj): 获取值

package ReflectionField;

import java.lang.reflect.Field;

public class Demo1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
//1、获取class字节码文件
Class clazz = Class.forName("ReflectionField.Student");
//2、获取所有的成员变量
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
//获取单个的成员变量
Field name = clazz.getDeclaredField("name");
System.out.println("name: " + name);

//获取权限修饰符
int modifiers = name.getModifiers();
System.out.println("modifiers: " + modifiers);

//获取成员的变量名
String n = name.getName();
System.out.println("n: " + n);

//获取变量的数据类型
Class<?> type = name.getType();
System.out.println("type: " + type);

Student s = new Student("zhangsan",23,"男");
//暴力反射:表示临时取消权限校验
name.setAccessible(true);
String value = (String) name.get(s);
System.out.println("value: " + value);
//修改对象里面记录的值
name.set(s,"lisi");

System.out.println(s);
}
}
public class Student {

private String name;
private int age;
public String gender;

public Student(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}

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;
}

@Override
public String toString() {
return "Student{" +
"name='" + name + '\\'' +
", age=" + age +
", gender'" + gender + '\\'' +
'}';
}
}

5、反射获取成员方法

Method就是成员方法
利用反射获取成员方法

(1)Class类中用于获取成员方法的方法

  • Method[] getMethods(): 返回所有公共成员方法对象的数组,包括继承的
  • Method[] getDeclarredMethods(): 返回所有成员方法对象的数组,不包括继承的
  • Method getMethod(String name,Class<?>…parameterTypes): 返回单个公共成员方法对象
  • Method getDeclaredMethod(String name,Class<?>…parameterTypes):返回单个成员方法对象

(2)Method类中用于创建对象的方法

  • Object invoke(Object obj,Object…args): 运行方法

参数一:用obj对象调用该方法

参数二:调用方法的传递的参数(如果没有就不写)

返回值:方法的返回值(如果没有就不写)

package ReflectionMethod;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

public class Text {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//1、获取class字节码文件对象
Class clazz = Class.forName("ReflectionMethod.Student");
//2、获取类里面的所有公共方法(包含父类中所有的公共方法)
// Method[] methods = clazz.getMethods();
// for (Method method : methods) {
// System.out.println(method);
// }
//获取所有的方法(不包含父类)
// Method[] methods1 = clazz.getDeclaredMethods();
// for (Method method : methods1) {
// System.out.println(method);
// }

//获取单个方法(根据方法参数不同,后面应该加上对应的class字节码
Method m = clazz.getDeclaredMethod("eat",String.class);
System.out.println(m);
Method m2 = clazz.getDeclaredMethod("eat",String.class,int.class);
System.out.println(m2);

//获取方法的修饰符
int modifiers = m2.getModifiers();
System.out.println(modifiers);

//获取方法的名字
String name = m2.getName();
System.out.println("name" + name);

//获取方法的形参
Parameter[] parameters = m2.getParameters();
for (Parameter parameter : parameters) {
System.out.println(parameter);
}

//获取方法抛出的异常
Class[] exceptions = m2.getExceptionTypes();
for (Class exception : exceptions) {
System.out.println(exception);
}

/*Method类中的创建对象的方法Object invoke(Object obj,Object…args): 运行方法
参数一:用obj对象调用该方法
参数二:调用方法的传递的参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)
*/
Student s = new Student();
m.setAccessible(true);
//参数一:s:不重方法的调用者
//参数二“汉堡包”:表示在调用方法的时候传递的实际参数
String result = (String)m.invoke(s,"汉堡包");
System.out.println(result);
}
}
public class Student {
private String name;
private int age;

public Student(){}
public Student(String name, int age) {
this.name = name;
this.age = age;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
public void sleep() {
System.out.println("睡觉");
}
private String eat(String something){
System.out.println("我再吃" + something);
return "奥利奥";
}
private void eat(String something, int a) throws IOException,NullPointerException {
System.out.println("你再吃" + something);
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\\'' +
", age=" + age +
'}';
}
}

赞(0)
未经允许不得转载:171主机测评 » 反射 定义、获取class对象的三种方式、获取构造方法、获取成员变量、获取成员方法(对应练习和笔记)
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址