本文主要是介绍Day68(获取运行时类的完整结构,调用运行时类的指定结构),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
获取运行时类的完整结构
通过反射获取运行时类的完整结构
Field、Method、Constructor、Superclass、Interface、Annotation
-
实现的全部接口
-
所继承的父类
-
全部的构造器
-
全部的方法
-
全部的Field
使用反射可以取得:
1.实现的全部接口
- public Class<?>[] getInterfaces()
确定此对象所表示的类或接口实现的接口。
2.所继承的父类
- public Class<? Super T> getSuperclass()
返回表示此Class 所表示的实体(类、接口、基本类型)的父类的Class。
3.全部的构造器
- public Constructor[] getConstructors()
返回此Class 对象所表示的类的所有public构造方法。
- public Constructor[] getDeclaredConstructors()
返回此Class 对象表示的类声明的所有构造方法。
Constructor类中:
-
取得修饰符:public int getModifiers();
-
取得方法名称: public String getName();
-
取得参数的类型:public Class<?>[] getParameterTypes();
4.全部的方法
-
public Method[] getDeclaredMethods()
-
返回此Class对象所表示的类或接口的全部方法
-
public Method[] getMethods()
返回此Class对象所表示的类或接口的public的方法
Method类中:
-
public Class<?> getReturnType()取得全部的返回值
-
public Class<?>[] getParameterTypes()取得全部的参数
-
public int getModifiers()取得修饰符
-
public Class<?>[] getExceptionTypes()取得异常信息
5.全部的Field
- public Field[] getFields()
返回此Class对象所表示的类或接口的public的Field。
- public Field[] getDeclaredFields()
返回此Class对象所表示的类或接口的全部Field。
Field方法中:
-
public int getModifiers() 以整数形式返回此Field的修饰符
-
public Class<?> getType() 得到Field的属性类型
-
public String getName() 返回Field的名称。
6.Annotation相关
-
get Annotation(Class annotationClass)
-
getDeclaredAnnotations()
7.泛型相关
获取父类泛型类型:Type getGenericSuperclass()
泛型类型:ParameterizedType
获取实际的泛型类型参数数组:getActualTypeArguments()
8.类所在的包Package getPackage()
Persons类
package com.lingxiang.reflection;
@MyAnnotation(value = "hi")
public class Persons extends Creature<String> implements Comparable<String>,MyInterface{private String name;int age;public int id;public Persons(){}@MyAnnotation(value = "abc")private Persons(String name){this.name = name;}Persons(String name,int age){this.name = name;this.age = age;}@MyAnnotationprivate String show(String nation){System.out.println("我的国籍是: " + nation);return nation;}public String display(String interest){return interest;}@Overridepublic void info() {System.out.println("我是一个人");}@Overridepublic int compareTo(String o) {return 0;}
}
父类Creature
package com.lingxiang.reflection;import java.io.Serializable;public class Creature<T> implements Serializable {private char gender;public double weight;private void breath(){System.out.println("生物呼吸");}public void eat(){System.out.println("生物进食");}
}
获取Field
package com.lingxiang.reflection;import org.junit.Test;import java.lang.reflect.Field;
import java.lang.reflect.Modifier;public class FieldTest {@Testpublic void test1(){Class clazz = Persons.class;//获取属性结构//getFields():获取当前运行时类及其父类中声明为public访问权限的属性Field[] fields = clazz.getFields();for (Field f : fields){System.out.println(f);}System.out.println();//getDeclaredFields():获取当前运行时类中声明的所属性。(不包含父类中声明的属性)Field[] declaredFields = clazz.getDeclaredFields();for (Field f : declaredFields){System.out.println(f);}}@Test//权限修饰符 数据类型 变量名public void test2(){Class clazz = Persons.class;Field[] declaredFields = clazz.getDeclaredFields();for (Field f : declaredFields){//权限修饰符int modifier = f.getModifiers();System.out.print(Modifier.toString(modifier)+"\t");//数据类型Class type = f.getType();System.out.print(type+"\t");//变量名String name = f.getName();System.out.print(name+"\n");}}}
获取Method
package com.lingxiang.reflection;import org.junit.Test;import java.lang.annotation.Annotation;
import java.lang.reflect.Method;public class MethodTest {@Testpublic void test1(){Class clazz = Persons.class;//getMethods():获取当前运行时类及其所父类中声明为public权限的方法Method[] methods = clazz.getMethods();for (Method m : methods){System.out.println(m);}//getDeclaredMethods():获取当前运行时类中声明的所方法。(不包含父类中声明的方法System.out.println();Method[] declaredMethods = clazz.getDeclaredMethods();for (Method m : declaredMethods){System.out.println(m);}}@Test//权限修饰符 返回值类型 方法名(参数类型 形参名 ...)Throws XxxException{}public void test2(){Class clazz = Persons.class;Method[] declaredMethods = clazz.getDeclaredMethods();for (Method m : declaredMethods){//获取方法声明的注解Annotation[] annotations = m.getAnnotations();for (Annotation a : annotations){System.out.println(a);}}}
}
获取其它
package com.lingxiang.reflection;import org.junit.Test;import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;public class OtherTest {/*获取构造器结构*/@Testpublic void test1() {Class clazz = Persons.class;//getConstructors():获取当前运行时类中声明为public的构造器Constructor[] constructors = clazz.getConstructors();for (Constructor c : constructors) {System.out.println(c);}//getDeclaredConstructors():获取当前运行时类中声明的所的构造器System.out.println();Constructor[] declaredConstructors = clazz.getDeclaredConstructors();for (Constructor c : constructors) {System.out.println(c);}}@Test/*获取运行时类的父类*/public void test2() {Class clazz = Persons.class;Class superclass = clazz.getSuperclass();System.out.println(superclass);}@Test/*获取运行时类的带泛型的父类*/public void test3() {Class clazz = Persons.class;Type genericSuperclass = clazz.getGenericSuperclass();ParameterizedType paraType = (ParameterizedType) genericSuperclass;Type[] actualTypeArguments = paraType.getActualTypeArguments();for (Type t : actualTypeArguments) {System.out.println(t.getTypeName());}System.out.println(genericSuperclass);}/*获取运行时类实现的接口*/@Testpublic void test4() {Class clazz = Persons.class;Class[] interfaces = clazz.getInterfaces();for (Class c : interfaces) {System.out.println(c);}System.out.println();//获取运行时类的父类实现的接口Class[] interfaces1 = clazz.getSuperclass().getInterfaces();for (Class c : interfaces1) {System.out.println(c);}}/*获取运行时类所在的包*/@Testpublic void test5() {Class clazz = Persons.class;Package pack = clazz.getPackage();System.out.println(pack);}/*获取运行时类声明的注解*/@Testpublic void test6(){Class clazz = Persons.class;Annotation[] annotations = clazz.getAnnotations();for (Annotation a : annotations){System.out.println(a);}}
}
小结:
1.在实际的操作中,取得类的信息的操作代码,并不会经常开发。
2.一定要熟悉java.lang.reflect包的作用,反射机制。
3.如何取得属性、方法、构造器的名称,修饰符等。
调用运行时类的指定结构
1.调用指定方法
通过反射,调用类中的方法,通过Method类完成。步骤:
1.通过Class类的getMethod(String name,Class…parameterTypes)方法取得一个Method对象,并设置此方法操作时所需要的参数类型。
2.之后使用Object invoke(Object obj, Object[] args)进行调用,并向方法中传递要设置的obj对象的参数信息。
Object invoke(Object obj, Object … args)
说明:
1.Object 对应原方法的返回值,若原方法无返回值,此时返回null
2.若原方法若为静态方法,此时形参Object obj可为null
3.若原方法形参列表为空,则Object[] args为null
4.若原方法声明为private,则需要在调用此invoke()方法前,显式调用方法对象的setAccessible(true)方法,将可访问private的方法。
2.调用指定属性
在反射机制中,可以直接通过Field类操作类中的属性,通过Field类提供的set()和get()方法就可以完成设置和取得属性内容的操作。
-
public Field getField(String name) 返回此Class对象表示的类或接口的指定的public的Field。
-
public Field getDeclaredField(String name)返回此Class对象表示的类或接口的指定的Field。
在Field中:
-
public Object get(Object obj) 取得指定对象obj上此Field的属性内容
-
public void set(Object obj,Object value) 设置指定对象obj上此Field的属性内容
关于setAccessible方法的使用
-
Method和Field、Constructor对象都有setAccessible()方法。
-
setAccessible启动和禁用访问安全检查的开关。
-
参数值为true则指示反射的对象在使用时应该取消Java语言访问检查。
-
提高反射的效率。如果代码中必须用反射,而该句代码需要频繁的被调用,那么请设置为true。
-
使得原本无法访问的私有成员也可以访问
-
-
参数值为false则指示反射的对象应该实施Java语言访问检查。
/*** 调用运行时类指定的结构:属性,方法,构造器*/
public class ReflectionTest1 {/*调用指定的属性:*/@Testpublic void test1() throws NoSuchFieldException, IllegalAccessException, InstantiationException {Class clazz = Persons.class;//创建运行时类的对象Persons p = (Persons) clazz.newInstance();//获取指定属性:要求属性声明为public//通常不用此方式Field id = clazz.getField("id");//设置对象的属性值id.set(p, 10);//获取当前属性的值int i = (int) id.get(p);System.out.println(i);}/*
调用指定的属性:*/@Testpublic void test2() throws IllegalAccessException, InstantiationException, NoSuchFieldException {Class clazz = Persons.class;//创建运行时类的对象Persons p = (Persons) clazz.newInstance();//1. getDeclaredField(String fieldName):获取运行时类中指定变量名的属性Field name = clazz.getDeclaredField("name");//2.保证当前属性是可访问的name.setAccessible(true);//3.获取、设置指定对象的此属性值name.set(p, "Tom");System.out.println(name.get(p));}/*调用指定的方法:*/@Testpublic void test3() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {Class clazz = Persons.class;Persons p = (Persons) clazz.newInstance();/*1.获取指定的某个方法getDeclaredMethod():参数1 :指明获取的方法的名称 参数2:指明获取的方法的形参列表*/Method show = clazz.getDeclaredMethod("show", String.class);//2.保证当前方法是可访问的show.setAccessible(true);/*3. 调用方法的invoke():参数1:方法的调用者 参数2:给方法形参赋值的实参invoke()的返回值即为对应类中调用的方法的返回值。*/Object o = show.invoke(p, "China");System.out.println(o);System.out.println("*************如何调用静态方法*****************");Method showDesc = clazz.getDeclaredMethod("showDesc");showDesc.setAccessible(true);//如果调用的运行时类中的方法没返回值,则此invoke()返回null//Object returnVal = showDesc.invoke(null);showDesc.invoke(Persons.class);}/*调用指定的构造器:*/@Testpublic void test4() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {Class clazz = Persons.class;/*1.获取指定的构造器getDeclaredConstructor():参数:指明构造器的参数列表*/Constructor constructor = clazz.getDeclaredConstructor(String.class);//2.保证此构造器是可访问的constructor.setAccessible(true);//3.调用此构造器创建运行时类的对象Persons p = (Persons)constructor.newInstance("乌龟");System.out.println(p);}
}
这篇关于Day68(获取运行时类的完整结构,调用运行时类的指定结构)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!