zoukankan      html  css  js  c++  java
  • 【java学习笔记】反射基础

    一.反射

      反射就是在剖析一个类,了解这个类的构造,创建这个类对应的对象。

    Class 代表字节码的类,代表类的类
    Field 代表属性的类
    Method 代表方法的类
    Constructor 代表构造方法的类
    Annotation 代表注解的类
    Package 代表包的类

    二.Class类

    2.1 获取Class对象:必须有意义

        ①通过类名.class的方式来获取对应类的字节码对象

     1 import java.util.List;
     2 
     3 public class ClassDemo {
     4     @SuppressWarnings("rawtypes")
     5     public static void main(String[] args)  {
     6 
     7         // 每一个Class对象对应了一个实际的类,因此要求每一个Class都必须有意义
     8         // 如果允许随意创建Class对象,就会导致Class对象没有实际对应的类
     9         // Class clz0 = new Class();
    10         
    11         // 通过类名.class的方式来获取一个字节码对象
    12         // clz表示的就是String的字节码
    13         Class<String> clz = String.class;
    14         System.out.println(clz);
    15 
    16         // clz2表示的就是List的字节码
    17         Class<List> clz2 = List.class;
    18         System.out.println(clz2);
    19         
    20         // clz3表示的就是String[]的字节码
    21         Class<String[]> clz3 = String[].class;
    22         System.out.println(clz3);
    23         
    24     }
    25 }
    类名.class

        ②通过对象.getClass()方法来获取这个对象对应的实际类的字节码对象

     1 public class ClassDemo {
     2     @SuppressWarnings("unchecked")
     3     public static void main(String[] args)  {
     4         Object str = "abc";
     5         Class<String> clz = (Class<String>) str.getClass();
     6         System.out.println(clz);
     7     }
     8 }
     9 
    10 //输出:class java.lang.String
    对象.getClass()

        ③通过Class.forName(类的全路径名)的方法来获取指定类的字节码对象

     1 import java.util.List;
     2 
     3 public class ClassDemo {
     4     @SuppressWarnings("unchecked")
     5     public static void main(String[] args) throws ClassNotFoundException  {
     6         Class<String> clz = (Class<String>) Class.forName("java.lang.String");
     7         System.out.println(clz);
     8         
     9         Class<List> clz2 = (Class<List>) Class.forName("java.util.List");
    10         System.out.println(clz2);
    11     }
    12 }
    13 
    14 //输出:
    15 //class java.lang.String
    16 //interface java.util.List
    Class.forName(类的全路径名)

    2.2创建由此对象表示的类的新实例

    2.2.1 newInstance

    字节码对象.newInstance();

    用处之举例:

        Cat和Dog都实现了Animal接口,利用向上造型,将字符串利用Properties进行更改,可实现任意创建Cat对象或者Dog对象。

     1 public class TestClassDemo {
     2     @SuppressWarnings("unchecked")
     3     public static void main(String[] args) throws Exception {
     4 
     5         // 表示获取了Animal类对应的字节码
     6         //"cn.hdu.reflection.Cat"可以用Properties进去获取
     7         Class<Animal> clz = (Class<Animal>) Class.forName("cn.hdu.reflection.Cat");
     8         
     9         // 要求类中必须有无参构造
    10         Animal a = clz.newInstance(); //产生对象
    11         System.out.println(a);
    12 
    13     }
    14 
    15 }
    16 
    17 interface Animal {
    18 }
    19 
    20 class Dog implements Animal {
    21 
    22     @Override
    23     public String toString() {
    24         return "Dog";
    25     }
    26 
    27 }
    28 
    29 class Cat implements Animal {
    30 
    31     @Override
    32     public String toString() {
    33         return "Cat";
    34     }
    35 
    36 }
    AnimalCatDog

    2.2.2 通过构造方法创建新实例

    //只能获取public构造方法
    Constructor<?>[] getConstructors()
    Constructor<T> getConstructor(类<?>... parameterTypes)  
    
    //不区分是否是public的构造方法
    Constructor<?>[] getDeclaredConstructors()  
    Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)  
    //需要用 Constructor对象.setAccessible(true);进行设置

    举例:

     1 import java.lang.reflect.Constructor;
     2 
     3 public class ClassGetConstructorDemo {
     4     public static void main(String[] args) throws Exception {
     5 
     6         // clz代表String类的字节码
     7         Class<String> clz = String.class;
     8 
     9         // String(String)
    10         // 只能获取public修饰的构造方法
    11         Constructor<String> constructorPublic = clz.getConstructor(String.class);
    12         String str = constructorPublic.newInstance("abc");
    13         System.out.println(str);
    14 
    15          // String(byte[], int, int)
    16         Constructor<String> constructorParameters = clz.getConstructor(byte[].class, int.class, int.class);
    17         String str2 = constructorParameters.newInstance(new byte[] { 97, 98, 99, 100 }, 1, 3);
    18         System.out.println(str2);
    19 
    20         // 获取指定的构造方法,不区分是否是public的
    21         Constructor<String> constructorPrivate = clz.getDeclaredConstructor(char[].class, boolean.class);
    22         // 暴力破解/暴力拆除
    23         constructorPrivate.setAccessible(true);
    24         String str3 = constructorPrivate.newInstance(new char[] { 'a', 'b', 'c' }, true);
    25         System.out.println(str3);
    26     }
    27 
    28 }
    getConstructor

    在String源码中是默认的,非public

    2.3 获取方法

    //public
    Method getMethod(String name, 类<?>... parameterTypes)  
    Method[] getMethods()  //获取所有公有方法(包含了父类的方法也包含Object类) 
    
    //非public
    Method getDeclaredMethod(String name, 类<?>... parameterTypes) 
    Method[] getDeclaredMethods() //获取所有的成员方法,包括私有的(不包括继承的)
    //m.setAccessible(true);
    
    //使用所指定的方法:Method的对象.invoke(Object obj, Object... args);
     1 import java.lang.reflect.Constructor;
     2 import java.lang.reflect.Method;
     3 
     4 public class ClassGetMethodDemo {
     5 
     6     public static void main(String[] args) throws Exception {
     7 
     8         Class<String> clz = String.class;
     9 
    10         // 表示String(String)
    11         Constructor<String> c = clz.getConstructor(String.class);
    12         String str = c.newInstance("abcdefg");
    13 
    14         // 获取charAt(int)
    15         // 只能获取public修饰的方法
    16         Method m = clz.getMethod("charAt", int.class);
    17         // 执行方法对象
    18         // 相当于char ch = str.charAt(3);
    19         char ch = (char) m.invoke(str, 3);
    20         System.out.println(ch);
    21 
    22         // 获取指定的方法
    23         Method m2 = clz.getDeclaredMethod("lastIndexOfSupplementary", int.class, int.class);
    24         m2.setAccessible(true);
    25         int i = (int) m2.invoke(str, 2, 3);
    26         System.out.println(i);    
    27     }
    28 
    29 }
    getMethod

    2.4 获取属性

    //public
    Field getField(String name)  
    Field[] getFields()  
    
    //非public
    Field getDeclaredField(String name)  
    Field[] getDeclaredFields()  
    //f.setAccessible(true);
    
    //Field类
    获取:Object get(Object obj) 
    设置:void set(Object obj, Object value)  
            void setChar(Object obj, char c) 
            void setDouble(Object obj, double d) 
            void setInt(Object obj, int i) 
            ... ...
     1 import java.lang.reflect.Constructor;
     2 import java.lang.reflect.Field;
     3 
     4 public class ClassGetFieldDemo {
     5     public static void main(String[] args) throws Exception {
     6 
     7         Class<String> clz = String.class;
     8 
     9         // 表示String(String)
    10         Constructor<String> c = clz.getConstructor(String.class);
    11         String str = c.newInstance("abcdefg");
    12 
    13         // 获取类中指定的属性
    14         Field f = clz.getDeclaredField("hash");
    15         f.setAccessible(true);
    16         System.out.println(f.get(str));
    17         // 设置属性的值
    18         f.set(str, 125);
    19         // 获取属性的值
    20         System.out.println(f.get(str));
    21     }
    22 }
    getField

    2.5 获取注解

    <A extends Annotation>A getAnnotation(类<A> annotationClass)  
    Annotation[] getAnnotations()  
    
    <A extends Annotation>A getDeclaredAnnotation(类<A> annotationClass)  
    Annotation[] getDeclaredAnnotations()  

    2.6 Class类其它常用方法

     1 import java.lang.reflect.TypeVariable;
     2 import java.util.ArrayList;
     3 import java.util.List;
     4 
     5 public class ClassDemo {
     6 
     7     @SuppressWarnings("rawtypes")
     8     public static void main(String[] args) {
     9 
    10         Class<String> clz = String.class;
    11 
    12         // 获取这个类实现的所有的接口
    13         Class[] ins = clz.getInterfaces();
    14         for (Class c : ins) {
    15             System.out.println(c);
    16         }
    17 
    18         // 获取父类
    19         Class superc = clz.getSuperclass();
    20         System.out.println(superc);
    21 
    22         // 获取类的全路径名
    23         System.out.println(clz.getName());
    24         // 获取类的简称
    25         System.out.println(clz.getSimpleName());
    26 
    27         // 获取所在的包
    28         System.out.println(clz.getPackage());
    29 
    30         List<String> list = new ArrayList<>();
    31         Class lclz = list.getClass();
    32         TypeVariable[] ts = lclz.getTypeParameters();
    33         for (TypeVariable typeVariable : ts) {
    34             System.out.println(typeVariable);
    35         }
    36 
    37         // 判断是否是一个枚举
    38         System.out.println(clz.isAnnotation());
    39         // 判断是否是一个基本类型
    40         System.out.println(clz.isPrimitive());
    41 
    42         // 判断参数是否是指定类型的实例的
    43         Object str = "abc";
    44         System.out.println(clz.isInstance(str));
    45         System.out.println(str instanceof String);
    46 
    47         // 判断两个类之间是否有继承关系
    48         System.out.println(Object.class.isAssignableFrom(String.class));
    49 
    50     }
    51 
    52 }
  • 相关阅读:
    关系数据理论之第三范式
    关系数据理论之第二范式
    关系数据理论之第一范式
    排序之外部排序
    排序之选择排序
    排序之希尔排序
    排序之基数排序
    排序之计数排序
    排序之堆排序
    排序之归并排序
  • 原文地址:https://www.cnblogs.com/kuotian/p/8516255.html
Copyright © 2011-2022 走看看