Java基础之反射机制(续)

320 阅读2分钟

回顾

在上篇Java基础之反射机制,讲解了Class实例是反射的源头,并且讲解了获取Class实例的三种方法:

  • 通过类名获取
Class clazz= Person.class;
  • 通过对象获取
Person p=new Person();
Class clazz1=p.getClass();
  • 通过Class类的静态属性
Class clazz3=Class.forName("com.zhang.Person");
 System.out.println(clazz3);

那么我们就可以利用这个Class实例做许多事情。

Class实例的使用

1.创建类的对象

String className="com.zhang.Person";
Class clazz= Class.forName(className);
Person person=(Person) clazz.newInstance();

Person 类需要空参的构造器

空参构造器不能private修饰

2. 获取类属性

Class clazz= Person.class;
Field[] fields= clazz.getFields();//只能获取运行时类及父类声明为public的属
for(int i=0;i<fields.length;i++){
  System.out.println(fields[i]);
}

 Field[] fields1 =clazz.getDeclaredFields();//获取运行时类所有的属性
for(Field f:fields1){
            System.out.println(f.getName());//获取属性名
            System.out.println(f.getModifiers());//获取权限修饰符
             int i= f.getModifiers();
            System.out.println(Modifier.toString(i));//转化成对应值
        }

3.获取类方法

Class clazz= Person.class;
Method[] m1= clazz.getMethods();//获取运行时类及其父类所有声明为public的方法
for(Method m:m1){
  System.out.println(m);
}
Method[] m1=clazz.getDeclaredMethods();//获取类本身声明的所有方法
      for(Method m:m1){
          System.out.println(m);
           Annotation[] an= m.getAnnotations();//获取注解
         for (Annotation a:an){
             System.out.println(a);
         }
          Class[] types= m.getParameterTypes();//获得方法的参数类型
         for(Class type:types){
             System.out.println(type);
         }
         Class re =m.getReturnType();//获得返回值类型
         System.out.println(re);
         
      Class[] es= m.getExceptionTypes();//获得异常类型
       for(Class e :es){
           System.out.println(e);
       }
      }

4.获取构造方法

Class clazz= Person.class;
       Constructor[] cs= clazz.getConstructors();//获得所有声明的构造方法
       for (Constructor c:cs){
           System.out.println(c);
       }

5.获取父类

Class clazz= Person.class;
Class cs=clazz.getSuperclass();//获取父类
Type type =clazz.getGenericSuperclass();//获取带泛型的父类
ParameterizedType param=(ParameterizedType)type;//获取传入父类的泛型
Type[] arg1=param.getActualTypeArguments();
System.out.println(((Class)arg1[0]).getName());

6.获取实现的接口

 Class[] in= clazz.getInterfaces();//获取接口
for (Class i:in){
    System.out.println(i);
}

7.获取类所在的包

 Class clazz= Person.class;
System.out.println(clazz.getPackage());

8.获取类的注解

Class clazz= Person.class;
Annotation[] an=clazz.getAnnotations();

利用反射调用运行时类中指定的方法和属性

1.调用属性

Class clazz= Person.class;
Field name=clazz.getField("name");//public权限的
Person p=(Person) clazz.newInstance();
name.set(p,"hello");

 Field age=clazz.getDeclaredField("age");//获取指定名属性
age.setAccessible(true);//设置访问权限
age.set(p,12);
System.out.println(p);

2.调用方法

 Class clazz= Person.class;
Person p=(Person) clazz.newInstance();//实例
Method m1= clazz.getMethod("show");//调用public修饰的方法
m1.invoke(p);//调用

  Class clazz= Person.class;
 Person p=(Person) clazz.newInstance();
  Method m1= clazz.getDeclaredMethod("display", String.class);//调用非public的指定方法
  m1.setAccessible(true);//设置权限
  m1.invoke(p,"china");//调用

3.调用静态方法

Class clazz= Person.class;
Method m1= clazz.getMethod("show");
m1.invoke(Person.class);//调用静态方法

4.调用指定的构造器

 Class clazz= Person.class;
Constructor cons= clazz.getDeclaredConstructor(String.class,int.class);
cons.setAccessible(true);
Person p=(Person) cons.newInstance("lily",16);
System.out.println(p);

总结

本篇首先介绍了利用Class实例如何获取类完整的结构,包括属性方法构造器注解和父类等等。然后接着介绍了具体利用反射我们如何调用指定的方法构造器和属性。这样整个反射的使用就打通了,下一篇讲解反射的一个重要应用--动态代理。

喜欢本文的朋友们,欢迎长按下图关注订阅号"我的编程笔记",收看更多精彩内容~~