-----------android培训、java培训、java学习型技术博客、期待与您交流!------------
反射
反射相关的api:
Java.lang.Class:代表一个类
Java.lang.reflect.Method:代表类的方法
Java.lang.reflect.Field:代表类的成员变量
Java.lang.reflect.Constructor:代表类的构造方法
理解反射的源头之Class类:
我们创建了一个类,通过(javac.exe),生成对应的.class文件,之后,我们使用java.exe加载(JVM的类加载器)此.class文件,每个.class文件就是一个Class的实例。
如何获取Class的实例:
1:引用类的.class属性:
如:Class clazz=Person.class;
Class clazz2=String.class;
2:通过运行时类的getClass()方法获取:
Person p=new Person();
Class clazz3=p.getClass();
3:通过Class的静态方法.forName(String name)方法获取
必须指明完整报名,完整路径
Class clazz4=Class.forName("com.itheima.java.Person");
4:通过类加载器
ClassLoader loader=this.getClass().getClassLoader();
Class clazz5=loader.loadClass("com.itheima.java.Person");
ClassLoader类加载器掌握如下:
如何获取ClassLoader对象:
通过Class对象的getClassLoader()方法获得:
ClassLoader loader=this.getClass().getClassLoader();
分类:
引导类加载器:系统类库的加载器(如Object,String)(无法获得)
扩展类加载器:lib包中的扩展加载器
系统类加载器:用户自己开发的类的加载器
应用:获取项目包下的文件内容:
获取配置文件中的参数
ClassLoader loader2=this.getClass().getClassLoader();
InputStream is=loader2.getResourceAsStream("com\\itheima\\java\\jdbc.properties");
Properties per=new Properties();
per.load(is);
String name=per.getProperty("user");
String password=per.getProperty("password");
创建运行时类的对象:
Class clazz=Person.class;
//使用newInstance()方法实际上是调用了Person类的空参的构造方法
//Person类要有空参的构造器,构造器的权限要足够
Person p=(Person) clazz.newInstance();
获取运行时类的属性:
Class clazz=Person.class;
//获取运行时类及其父类中声明为public的属性
Field [] fields=clazz.getFields();
for(Field f:fields){
System.out.println(f.getName());
}
//获取运行时类中声明的属性
Field [] fields1=clazz.getDeclaredFields();
for(Field f:fields1){
System.out.println(f.getName());
}
获取属性的修饰符,类型
for(Field f:fields1){
//获取每个属性的修饰符
int i=f.getModifiers();
String str=Modifier.toString(i);
System.out.print(str);
//获取每个属性的类型
Class type=f.getType();
System.out.print(type.getName());
System.out.println();
}
获取运行时类的方法:
Class clazz=Person.class;
//获取运行时类及其父类中声明为public的方法
Method[] methods=clazz.getMethods();
for(Method m:methods){
System.out.println(m.getName());
}
//获取运行时类中本身声明的方法
Method[] methods1=clazz.getDeclaredMethods();
for(Method m:methods1){
System.out.println(m.getName());
}
获取方法的结构:
for(Method m:methods1){
//获取方法的注解annotation
Annotation[] ann=m.getAnnotations();
for(Annotation a:ann){
System.out.println(a);
}
//权限修饰符
String str=Modifier.toString(m.getModifiers());
System.out.print(str);
//返回值类型
Class returnType=m.getReturnType();
System.out.print(returnType.getName());
//方法名
System.out.print(m.getName());
//形参列表
Class[] para=m.getParameterTypes();
for(Class c:para){
System.out.print(c.getName());
}
}
获取父类:
Class clazz=Person.class;
Type type=clazz.getGenericSuperclass();
获取父类的泛型:
Type type=clazz.getGenericSuperclass();
System.out.println(type);
//强转为ParameterizedType子类对象
ParameterizedType pt=(ParameterizedType)type;
//获取泛型数组
Type[] types=pt.getActualTypeArguments();
调用运行时类的属性
Field name=clazz.getField("name");
Person p=(Person) clazz.newInstance();
name.set(p, "zhangsan");
调用声明为非public的属性
Field age=clazz.getDeclaredField("age");
age.setAccessible(true);
age.set(p, 12);
调用运行时类的方法
Class clazz=Person.class;
Method m=clazz.getMethod("show");
Person p=(Person) clazz.newInstance();
//invoke()方法的返回值既是原方法的返回值
m.invoke(p);
对于静态方法的调用
m.invoke(Person.class);
不用使用对象,直接使用类.class
调用修饰符为非public且有参数的方法
Method m1=clazz.getDeclaredMethod("display", String.class,Integer.class);
m1.setAccessible(true);
m1.invoke(p, "zhagnsan",20);
invoke()返回值既是原方法的返回值
调用有参且调用修饰符为非public的构造方法
Constructor con=clazz.getDeclaredConstructor(String.class,Integer.class);
con.setAccessible(true);
Person p2=(Person) con.newInstance("zhangsan",21);