本帖最后由 小石姐姐 于 2018-4-25 15:55 编辑
Java反射机制概述及应用
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态
调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该象。而解剖使用的就是Class类中的方法.所以先要获
取到每一个字节码类的字节码文件对文件对应的Class类型的对象.
通过反射获取构造方法并使用:
获取构造方法
getConstructors
getDeclaredConstructors
创建对象
newInstance()
con.newInstance(“zhangsan", 20);
通过反射获取成员变量并使用:
获取所有成员
getFields()
getDeclaredFields()
获取单个成员
getField()
getDeclaredField()
修改成员的值:
set(Object obj,Object value)
将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
通过反射获取成员方法并使用:
获取所有方法
getMethods
getDeclaredMethods
获取单个方法
getMethod
getDeclaredMethod
暴力访问
method.setAccessible(true);
------------------------------------------------------
package com.jiuye_zikan_day12;
/*
* 反射的前提
* 要获取类的对象(Class对象)
*
* 三种方式获取的字节码对象是相等的(地址相同)
* clazz==clazz2==clazz3
*
*/
public class 反射概述_字节码对象 {
public static void main(String[] args) throws ClassNotFoundException {
//通过Object的getClass()方法获取,必须要有对象
Student s = new Student ();
Class clazz = s.getClass();
//通过类名获取字节码对象
Class clazz2 = Student.class;
//通过类方法
Class clazz3 = Class.forName("com.jiuye_zikan_day12.Student");
System.out.println(clazz);
/*Output:
class com.jiuye_zikan_day12.Student
*///:~
}
}
class Student{
}
----------------------------------
>>>>>>>> 使用反射获取类的构造方法 并创建该类的对象 <<<<<<<<<<
package com.jobday13;
/*
* 通过反射获取构造方法并使用:
* 1. Constructor<?>[] getConstructors() //获取公共的构造函数(public修饰的)
* //返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对
* //象所表示的类的所有公共构造方法。
* (将构造函数以对象的形式返回,只能获取public修饰的构造)
*
* 2. Constructor<T> getConstructor(Class<?>...parameterTypes)
* //返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
//根据参数返回具体的构造
*
* 3. T newInstance(); //使用无参构造创建对象
*
* Constructor 类的方法:
* 4. T newInstance(Object... initargs))
* // 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,
* //并用指定的初始化参数初始化该实例。
* //(它是一个可变参数,跟据类的构造情况,可以传参,也可以不传参数)
*
*
*
* 方法 1.2.3.为 Constructor类的方法
* 当我们使用无参构造创建对象时可以使用Class类的newInstance()方法,比较方便
*
*
*
*
* Constructor 类:
* Constructor 提供关于类的单个构造方法的信息以及对它的访问权限。
Constructor 允许在将实参与带有底层构造方法的形参的 newInstance() 匹配时进行扩展转换,
但是如果发生收缩转换,则抛出 IllegalArgumentException。
*/
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class _2_反射获取构造方法_并使用 {
public static void main(String[] args) throws ReflectiveOperationException {
//获取Student类的字节码对象
Class clazz = Class.forName("com.jobday13.Student");
//方法一
//Constructor<?>[] getConstructor()
// 获取公共构造函数(clazz);
//方法二.1
//Constructor<T> getConstructor(Class<?>...parameterTypes)
//不传参数时
// 获取无参构造_1(clazz);
//方法二.2
//Constructor<T> getConstructor(Class<?>...parameterTypes)
// 使用带参构造创建对象(clazz);
//方法三
//T newInstance(); //使用Class类的方法创建对象
Object obj = clazz.newInstance();
System.out.println(obj);
/*Output:
Student [name=null, age=0]
//创建了一个Student对象
*///:~
}
//方法二.2
private static void 使用带参构造创建对象(Class clazz)
throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
//Constructor<T> getConstructor(Class<?>...parameterTypes)
Constructor c = clazz.getConstructor(String.class,int.class);
System.out.println(c);
/*Output:
public com.jobday13.Student(java.lang.String,int)
//
*///:~
//通过 c 这个有参构造创建一个Student对象
Object obj = c.newInstance("苹果",25);
//此处必须传入参数,否则报错
//java.lang.IllegalArgumentException: wrong number of arguments
// "参数错误"
System.out.println(obj);
/*Output:
Student [name=苹果, age=25]
//创建成功
*///:~
}
//方法二.1
private static void 获取无参构造_1(Class clazz)
throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
//Constructor<T> getConstructor(Class<?>...parameterTypes)
Constructor cs = clazz.getConstructor();//它使用的是可变参数,因此先使用无参
System.out.println(cs);
/*Output:
public com.jobday13.Student()
//获取的是无参构造
*///:~
//使用获取的无参构造创建对象
Object obj = cs.newInstance();
System.out.println(obj);
/*Output:
public com.jobday13.Student()
Student [name=null, age=0]
//获取了一个Student对象,参数都是默认值
*///:~
}
//方法一:
private static void 获取公共构造函数(Class clazz) {
//Constructor<?>[] getConstructor()
Constructor[] cs = clazz.getConstructors();
for(int i=0;i<cs.length;i++){
System.out.println(cs);
}
/*Output:
public com.jobday13.Student() //空参构造
public com.jobday13.Student(java.lang.String,int) //带参构造
public com.jobday13.Student(java.lang.String) //带参构造
//有参构造内到的 参数类型都是全路径 (java.lang.String)
*///:~
}
}
class Student {
String name;
int age;
public Student() {
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Student(String name) {
super();
this.name = name;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
-----------------------------------
>>>>>>> 反射获取 私有成员 <<<<<<<<<<
package com.jobday13;
import java.lang.reflect.Field;
/*
* 通过反射获取私有成员变量并使用:
* //只能看见所有个字段,不能访问(想访问的话,就要通过方法取消访问权限)
* Field[] getDeclaredFields() //获取所有的字段(public,private都可以)
* Field getDeclaredField(String name) //获取指定的字段
*
* AccessibleObject 类是 Field、Method 和 Constructor 对象的基类.
*
* Field 的父类 AccessibleObject 的方法:
* void setAccessible(boolean flag)
//将此对象的 accessible 标志设置为指示的布尔值。 true为取消java默认访问检查
Field 也可以使用这个方法;
*
*/
public class 通过反射获取私有成员变量_使用_2 {
public static void main(String[] args) throws ReflectiveOperationException {
//获取学生类的字节码对象
Class clazz = Class.forName("com.jobday13.Student");
//通过字节码对象创建学生对象
Object stu = clazz.newInstance();
//获取私有字段对象
Field f = clazz.getDeclaredField("name");
//设置反射式取消java默认的的访问检查,暴力访问
f.setAccessible(true);
Object name = f.get(stu);
System.out.println(name);
/*Output:
橘子
//访问成功
*///:~
}
}
----------------------------------------------
>>>>>>>> 反射获取 成员方法 <<<<<<<<<<<
package com.jobday13;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/*
* 通过反射获取成员方法并使用:
* Method getMethod(String name,Class<?>...parameterTypes)
* //可以传入参数也可以不用参数
*
* Method:
* Object invoke(Object obj, Object...args)
*
*
*/
public class 反射_获取成员方法_1 {
public static void main(String[] args) throws ReflectiveOperationException {
//获取学生类的字节码对象
Class clazz = Class.forName("com.jobday13.Student");
//获取学生对对象
Object stu = clazz.newInstance();
// 获取无返回值的方法(clazz, stu);
// 获取有参无返回值的方法(clazz, stu);
// 获取无参有返回值的方法(clazz, stu);
}
private static void 获取无参有返回值的方法(Class clazz, Object stu)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
//获取无参有返回值的方法
Method m = clazz.getMethod("getName");
Object obj = m.invoke(stu);
System.out.println(obj);
}
private static void 获取有参无返回值的方法(Class clazz, Object stu)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, NoSuchFieldException {
//获取有参无返回值的方法
Method m = clazz.getDeclaredMethod("setName",String.class);
m.setAccessible(true);
m.invoke(stu, "haha");
Field f = clazz.getDeclaredField("name");
Field g = clazz.getDeclaredField("age");
f.setAccessible(true);
g.setAccessible(true);
System.out.println(g.get(stu));
System.out.println(f.get(stu));
}
private static void 获取无返回值的方法(Class clazz, Object stu)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
//获取无返回值的方法
Method m = clazz.getMethod("method");
m.invoke(stu);
/*Output:
我是Student的无参无返回值方法
//这个方法是在Student类的method方法中定义的输出语句
*///:~
}
}
|
|