您的位置 首页 java

java反射reflection

/**

* reflection反射

* 初次创建某一个类的对象时, JVM 会先通过类加载器ClassLoader将类文件xxx.class从磁盘中加载到内存(io操作)

* 在方法区中将类生成一个类对象 Class <xxx>对象,类对象/Class对象中有类文件的所有信息,每个类的Class对象只生成一个,用来创建类的所有对象

* 通过这个类的唯一的Class对象创建类的对象,当第二次及以后创建对象时,同样使用这个Class对象创建,不再重复加载类文件

*/

public class TestReflection1 implements Serializable {

//创建一个类

String name;

public int age;

public TestReflection1(String name, int age) {

this.name = name;

this.age = age;

}

private TestReflection1(String name) {

this.name = name;

}

//私有构造器

public TestReflection1(int age) {

this.age = age;

}

public TestReflection1() {

}

@Override

public String toString() {

return “TestReflection1{” +

“name='” + name + ‘\” +

“, age=” + age +

‘}’;

}

private void printAge(){

System.out.println(age);

}

//私有方法

public boolean setAge(int a){

age = a;

return true;

}

}

class GetClass{

public static void main(String[] args) {

TestReflection1 t1 = new TestReflection1(“quan”,20);

//Class对象在方法区,新的对象在堆heep,变量t1在栈stack中main栈帧中

Class<? extends TestReflection1> tClass = t1.getClass();

//通过实例化的对象.getClass()得到对象所属的类的Class对象,返回类型为Class<? extends 类名>,Class对象只有一份,所有实例化对象调用.getClass()会返回同一个Class对象

//每个 实例化 对象都是由这一个Class对象创建的

System.out.println(tClass);

//Class对象.toString() 返回“class 包名.类名”

System.out.println(tClass.getName());

//.getName()返回”包名.类名”

Class<GetClass> getClassClass = GetClass.class;

//通过类的静态属性.class得到Class对象,每个类都有class静态属性,当内存中没有该Class对象时JVM会去磁盘中加载

try {

Class<?> aClass = Class.forName(” java .lang.String”);

//通过Class类的 静态方法 .forName(String className)得到Class对象, 字符串 必须是完整的”包名.类名”,返回类型为Class<?>因为编译时没有解析字符串只能用 通配符

System.out.println(aClass);

} catch (ClassNotFoundException e) {

throw new Runtime Exception (e);

}

Constructor <?>[] declaredConstructors = tClass.getDeclaredConstructors();

//Class对象.getDeclaredConstructors()方法返回构造器类数组Constructor[],declared声明的,返回的是这个类中的所有 构造器 类的对象,包括private等四种访问控制符修饰的所有构造器对象

for (Constructor<?> c :

declaredConstructors) {

System.out.println(c);

}

/*结果

public TestReflection1()

public TestReflection1(int)

private TestReflection1(java.lang.String)

public TestReflection1(java.lang.String,int)

*/

Constructor<?>[] constructors = tClass.getConstructors();

//不加declared的get只返回public的构造器

System.out.println(Arrays.toString(constructors));

//结果:[public TestReflection1(), public TestReflection1(int), public TestReflection1(java.lang.String,int)]

try {

Constructor<? extends TestReflection1> declaredConstructor = tClass.getDeclaredConstructor(int.class);

//不加s的get返回单个构造器,需要传入Class<?>…p可变参数对应构造器的形参类型,这里传入的是int.class即int的Class对象,返回只传一个int参数的构造器

System.out.println(declaredConstructor);

//结果:public TestReflection1(int)

// System.out.println(tClass.getConstructor(String.class));

//不加declared不加s,只查找public的构造器,但TestReflection1(String name)是private的,所以找不到传参为String的构造器,抛出异常java.lang.NoSuchMethodException: TestReflection1.<init>(java.lang.String)

System.out.println(tClass.getConstructor( null ));

//只传null对应无参构造器,结果为:public TestReflection1() ,idea提示将null改为(Class<?>)null

// System.out.println(tClass.getConstructor(int.class,String.class));

//参数顺序和构造器形参顺序不同也会报错, 形参 顺序不同可以构成重载

Constructor<? extends TestReflection1> constructor = tClass.getConstructor(String.class, int.class);

TestReflection1 yang = constructor.newInstance(“yang”, 20);

//构造器对象.newInstance(Object…args)方法会生成新的对象,要求传入的参数和构造器的形参类型一致

} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {

throw new RuntimeException(e);

}

Field[] fields = tClass.getFields();

//.getFields()方法返回public的属性Field[]数组,和构造器对象一样,属性也是对象,这里的Field指成员变量,属于对象,不包含属于类的 静态变量

System.out.println(Arrays.toString(fields));

//结果为:[public int TestReflection1.age]

for (Field declaredField : tClass.getDeclaredFields()) {

//加Declared忽略访问控制符,返回所有Field

System.out.print(declaredField.getName()+”\t”);

//.getName()返回属性的名字,结果:name age

}

try {

Field age = tClass.getField(“age”);

//不加s返回单个,查找和传参的字符串名字一致的属性,public的属性

System.out.println(age);

//结果:public int TestReflection1.age

System.out.println(tClass.getDeclaredField(“name”));

//加declared忽略访问控制符

TestReflection1 t2 = tClass.newInstance();

//通过Class对象.newInstance()创建无参的实例

age.set(t2,23);

//Field对象.set(类的对象,值) 用于设定指定类的对象的成员变量的值,上面通过.getField(“age”)得到了age属性的Field对象,引用变量为age

//通过Field对象age.set对指定t2的属性age的值进行设定,设定的值的类型同样需要小于等于属性的类型

System.out.println(age.get(t2));

//Field对象.get(类的对象)返回指定对象的成员变量的值,使用age.get()会返回age属性的值,传参t2会返回t2对象的age属性的值,返回值类型为Object

age.setInt(t2,24);

int i = age.getInt(t2);

//使用指定具体类型的set、get,setInt要求参数为int类型,getInt返回int类型参数而不是Object

//对于属性的使用和正常通过对象调用一样,受访问控制符的限制,在类外不能查改private属性(除非关闭安全检查)

} catch (NoSuchFieldException | IllegalAccessException | InstantiationException e) {

throw new RuntimeException(e);

}

Method[] methods = tClass.getMethods();

//.getMethods()返回所有public修饰的普通方法对象数组Method[]

for (Method m :

methods) {

System.out.println(m);

}

//继承的public方法也会返回,比如继承Object类的public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException

System.out.println(Arrays.toString(tClass.getDeclaredMethods()));

//返回类内声明的所有方法,declared声明,通过继承得到的但是类内没有声明的方法不会返回

// 结果为:[public java.lang.String TestReflection1.toString(), private void TestReflection1.printAge(), public boolean TestReflection1.setAge(int)]

// 返回内容中有 toString 是因为重写了toString方法

try {

Method method1 = tClass.getMethod(“setAge”, int.class);

//.getMethod(String name,Class<?>…types)和getConstructor()方法类似,需要指定方法名和形参列表,只能查找public修饰的方法

System.out.println(method1.getName());

//.getName()返回方法名,结果:setAge

System.out.println(tClass.getDeclaredMethod(“printAge”));

//加declared忽略访问控制符,无参方法只传方法名

TestReflection1 t3 = tClass.newInstance();

Method setAge = tClass.getDeclaredMethod(“setAge”,int.class);

Method printAge = tClass.getDeclaredMethod(“printAge”);

Object a = setAge.invoke(t3, 23);

//Method方法对象.invoke(类的对象,对应形参的参数值),调用哪个方法对哪个对象。invoke调用,返回的是方法的返回值,setAge()方法返回 boolean ,向上转换为Object返回

System.out.println(a);

//结果:true

// Object pr = printAge.invoke(t3);

//对t3调用printAge方法,无参数,方法声明void时invoke()返回null,但由于printAge()方法为private,调用时抛异常java.lang.IllegalAccessException: Class GetClass can not access a member of class TestReflection1 with modifiers “private”

printAge.setAccessible(true);

//通过.setAccessible(true)关闭安全检查,设为true后JVM不再对该对象的调用检查访问控制符

Object pr = printAge.invoke(t3);

//不再报错,accessible可使用的,默认setAccessible(false)开启安全检查,受到访问控制符修饰的属性、方法、构造器等对象均可以通过setAccessible(true)关闭安全检查

} catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {

throw new RuntimeException(e);

}

String n = tClass.getName();

//.getName()返回 包名.类名

Package aPackage = String.class.getPackage();

//.getPackage()返回包对象

System.out.println(aPackage);

//结果:package java.lang, Java Platform API Specification, version 1.8

System.out.println(aPackage.getName());

//结果: java.lang

System.out.println(tClass.getSimpleName());

//.getSimpleName()返回不含包名的类名

Class<?> superclass = tClass.getSuperclass();

//.getSuperclass()返回父类

System.out.println(superclass);

//结果为:class java.lang.Object

Class<?>[] interfaces = tClass.getInterfaces();

//.getInterfaces()返回当前类所实现的所有接口的Class对象数组

System.out.println(Arrays.toString(interfaces));

//结果为:[interface java.io.Serializable]

}

}

文章来源:智云一二三科技

文章标题:java反射reflection

文章地址:https://www.zhihuclub.com/195601.shtml

关于作者: 智云科技

热门文章

网站地图