JavaSE - [12] 高级部分之反射

反射的概述

Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期
借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内
部属性及方法。
加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个
类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可
以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看
到类的结构,所以,我们形象的称之为: 反射


反射正常方式对比
Java 反射机制提供的功能

在运行时判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时获取泛型信息
在运行时调用任意一个对象的成员变量和方法
在运行时处理注解
生成动态代理

动态语言 vs 静态语言

1 、动态语言
是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化。通俗点说就是 在运行时代码可以根据某些条件改变自身结构。
主要动态语言:Object-C、C#、JavaScript、PHP、Python、Erlang。
2 、静态语言
与动态语言相对应的,运行时结构不可变的语言就是静态语言。如Java、C、C++。

反射的API

 java.lang.Class: 代表一 个类
 java.lang.reflect.Method: 代表类的方法
 java.lang.reflect.Field: 代表类的成员变量
 java.lang.reflect.Constructor: 代表类的构造器
 … …

反射之前,类的实例化等操作
使用反射,实现同上的操作

在Object类中定义了以下的方法,此方法将被所有子类继承:
● public final Class getClass()以上的方法返回值的类型是一个Class类,
此类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称。


Class

Class 类 类
 对象照镜子后可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接
口。对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含
了特定某个结构(class/interface/enum/annotation/primitive type/void/[])的有关信息。
 Class本身也是一个类
 Class 对象只能由系统建立对象
 一个加载的类在 JVM 中只会有一个Class实例
 一个Class对象对应的是一个加载到JVM中的一个.class文件
 每个类的实例都会记得自己是由哪个 Class 实例所生成
 通过Class可以完整地得到一个类中的所有被加载的结构
 Class类是Reflection的根源,针对任何你想动态加载、运行的类,唯有先获得相应的Class对象


Class的常用方法
反射的强大:调用类的私有结构
public class User {
    private String name;
    private String email;
    private String phone;
    private String password;
    private int age;
    private double price;

    public User(String name, String email, String phone){
        this.name = name;
        this.email = email;
        this.phone = phone;
    }
    public User(String name, String email, String phone, String password, int age, double price) {
        this.name = name;
        this.email = email;
        this.phone = phone;
        this.password = password;
        this.age = age;
        this.price = price;
    }

    public User() {
    }

    private User(String name){
        this.name = name;
    }

    private User(String name,String email){
        throw new Error("此处不可以创建对象,死了这条心吧");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return age == user.age &&
                Double.compare(user.price, price) == 0 &&
                Objects.equals(name, user.name) &&
                Objects.equals(email, user.email) &&
                Objects.equals(phone, user.phone) &&
                Objects.equals(password, user.password);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, email, phone, password, age, price);
    }


    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", phone='" + phone + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                ", price=" + price +
                '}';
    }

    public void show() {
        System.out.println("User.show");
    }

    private void privateShow() {
        System.out.println("User.privateShow");
    }
}
public class Test1 {
    public static void main(String[] args) {
        User user1 = new User();
        user1.setName("demo");
        user1.setAge(18);
        System.out.println(user1);
        user1.show();
        //在User外部.不可以通过User对象访问私有
        System.out.println("---------------以下是反射 调用公共构造---------------------");
        //使用反射
        Class clazz = User.class;
        try {
            Constructor constructor = clazz.getConstructor(String.class,String.class,String.class);
            Object hello = constructor.newInstance("hello",null,null);
            User user2 = (User) hello;
            user2.show();
            Method show = clazz.getDeclaredMethod("show");
            show.invoke(hello);
            System.out.println(user2);
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("---------------以下是反射 调用私有无异常构造---------------------");
        try {
            Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class);
            declaredConstructor.setAccessible(true);
            User user3 = (User)declaredConstructor.newInstance("123");
            System.out.println(user3);
            user3.show();
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("---------------以下是反射 调用私有有异常构造---------------------");
        try {
            Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class,String.class);
            declaredConstructor.setAccessible(true);
            User user4 = (User)declaredConstructor.newInstance("123","hahahah");
            System.out.println(user4);
            user4.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

打印结果

User{name='demo', email='null', phone='null', password='null', age=18, price=0.0}
User.show
---------------以下是反射 调用公共构造---------------------
User.show
User.show
User{name='hello', email='null', phone='null', password='null', age=0, price=0.0}
---------------以下是反射 调用私有无异常构造---------------------
User{name='123', email='null', phone='null', password='null', age=0, price=0.0}
User.show
---------------以下是反射 调用私有有异常构造---------------------
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at cn.icanci.reflection.Test1.main(Test1.java:51)
Caused by: java.lang.Error: 此处不可以创建对象,死了这条心吧
    at cn.icanci.reflection.User.<init>(User.java:42)

如果也不想通过反射创建对象,可以先私有构造函数,然后构造函数里面抛出异常

如何看待反射和封装性两个技术

建议直接使用new的方式
会使用反射的方式,在编译的时候,不知道去创建那个对象

Class 类的理解

1.类的加载过程
程序经过javac.exe 之后,会生成字节码文件,然后 java.exe 命令对某个字节码文件进行解释运行,然后加载到内存中,此过程就是类的加载 加载在内存中的类,就是一个 Class 的实例运行时类
2.Class实例就对应者一个运行时的类
3.加载在内存中的运行时类,会缓存一段时间,在此事件之内,可以通过不同的方式来获取

获取 Class实例的4种方式

1) 前提:若已知具体的类,通过类的class属性获取,该方法最为安全可靠,程序性能最高
实例:Class clazz = String.class;
2) 前提:已知某个类的实例,调用该实例的getClass()方法获取Class对象
实例:Class clazz = “www.icanci.cn”.getClass();
3) 前提:已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,可能抛出 ClassNotFoundException
实例:Class clazz = Class.forName(“java.lang.String”);
4)其他方式(不做要求)
ClassLoader cl = this.getClass().getClassLoader();
Class clazz4 = cl.loadClass(“类的全类名”);

public class Test3 {
    public static void main(String[] args) {
        //方法1
        Class clazz = User.class;
        System.out.println(clazz);

        //方法2
        try {
            Class clazz1 = Class.forName("cn.icanci.reflection.User");
            System.out.println(clazz1);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //方法3
        User user = new User();
        Class clazz2 = user.getClass();
        System.out.println(clazz2);
        //方法4
        //使用类的加载器
        ClassLoader classLoader = Test3.class.getClassLoader();
        try {
            Class clazz4 = classLoader.loadClass("cn.icanci.reflection.User");
            System.out.println(clazz4);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //加载在内存中的运行时类,会缓存一段时间,在此事件之内,可以通过不同的方式来获取
        System.out.println(clazz == clazz2);
    }
}

打印

lass cn.icanci.reflection.User
class cn.icanci.reflection.User
class cn.icanci.reflection.User
class cn.icanci.reflection.User
true

哪些类型可以有Class 对象?
(1)class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类
(2)interface:接口
(3)[]:数组
(4)enum:枚举
(5)annotation:注解@interface
(6)primitive type:基本数据类型
(7)void

public class Test2 {
    public static void main(String[] args) {
        Class c1 = Object.class;
        Class c2 = Comparable.class;
        Class c3 = String[].class;
        Class c4 = int[][].class;
        Class c5 = ElementType.class;
        Class c6 = Override.class;
        Class c7 = int.class;
        Class c8 = void.class;
        Class c9 = Class.class;
        int[] a = new int[10];
        int[] b = new int[100];
        int[][] c = new int[2][3];
        int[][] d = new int[4][4];
        Class c10 = a.getClass();
        Class c11 = b.getClass();
        Class c12 = c.getClass();
        Class c13 = d.getClass();
// 只要元素类型与维度一样,就是同一个Class
        System.out.println(c10 == c11);
        System.out.println(c12 == c13);
    }
}
true
true
理解类的加载过程
类的加载过程

加载:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口(即引用地址)。所有需要访问和使用类数据只能通过这个Class对象。这个加载的过程需要类加载器参与。
链接:将Java类的二进制代码合并到JVM的运行状态之中的过程。
验证:确保加载的类信息符合JVM规范,例如:以cafe开头,没有安全方面的问题
准备:正式为类变量(static)分配内存并 设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配。
解析:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程。
初始化:
执行类构造器<clinit>()方法的过程。类构造器<clinit>()方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。(类构造器是构造类信息的,不是构造该类对象的构造器)。
当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化。
虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确加锁和同步。

ClassLoader 的理解
public class Test4 {
    public static void main(String[] args) {
        System.out.println(A.m);
    }
}

class A {
    static {
        m = 300;
    }

    static int m = 100;
    
}
//第二步:链接结束后m=0
//第三步:初始化后,m的值由<clinit>()方法执行决定
// 这个A的类构造器<clinit>()方法由类变量的赋值和静态代码块中的语句按照顺序合并产生,类似于
// <clinit>(){
// m = 300;
// m = 100;
// }

什么时候会发生类初始化
 类的主动引用 ( 一定会发生类的初始化 )
 当虚拟机启动,先初始化main方法所在的类
 new一个类的对象
 调用类的静态成员(除了final常量)和静态方法
 使用java.lang.reflect包的方法对类进行反射调用
 当初始化一个类,如果其父类没有被初始化,则先会初始化它的父类
 类的被动引用 ( 不会发生类的初始化 )
 当访问一个静态域时,只有真正声明这个域的类才会被初始化
 当通过子类引用父类的静态变量,不会导致子类初始化
 通过数组定义类引用,不会触发此类的初始化
 引用常量不会触发此类的初始化(常量在链接阶段就存入调用类的常
量池中了)

类加载

类加载器的作用:
 类加载的作用:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口。
 类缓存:标准的JavaSE类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,它将维持加载(缓存)一段时间。不过JVM垃圾回收机制可以回收这些Class对象。


类加载器

• //1.获取一个系统类加载器
• ClassLoader classloader = ClassLoader.getSystemClassLoader();
• System.out.println(classloader);
• //2.获取系统类加载器的父类加载器,即扩展类加载器
• classloader = classloader.getParent();
• System.out.println(classloader);
• //3.获取扩展类加载器的父类加载器,即引导类加载器
• classloader = classloader.getParent();
• System.out.println(classloader);
• //4.测试当前类由哪个类加载器进行加载
• classloader = Class.forName("exer2.ClassloaderDemo").getClassLoader();
• System.out.println(classloader);
• //5.测试JDK提供的Object类由哪个类加载器加载
• classloader =
• Class.forName("java.lang.Object").getClassLoader();
• System.out.println(classloader);
• //*6.关于类加载器的一个主要方法:getResourceAsStream(String str):获取类路
径下的指定文件的输入流
• InputStream in = null;
• in = this.getClass().getClassLoader().getResourceAsStream("exer2\test.properties");
• System.out.println(in);

public class Test5 {
    public static void main(String[] args) {
        ClassLoader classLoader = Test5.class.getClassLoader();
        System.out.println(classLoader);

        ClassLoader parent = classLoader.getParent();
        System.out.println(parent);

        ClassLoader parent1 = parent.getParent();
        System.out.println(parent1);

    }
}
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@6d6f6e28
null
使用 ClassLoader 加载配置文件
public class Test6 {
    public static void main(String[] args) {
        Properties props = new Properties();
        FileInputStream in = null;
        try {
            in = new FileInputStream(new File("jdbc.properties"));
            props.load(in);
            System.out.println(props.get("username"));
            System.out.println(props.get("password"));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        //使用类加载器读取配置文件
        ClassLoader classLoader = Test6.class.getClassLoader();
        InputStream is = classLoader.getResourceAsStream("jdbc.properties");
        try {
            props.load(is);
            String username = props.getProperty("username");
            String password = props.getProperty("password");
            System.out.println(username + " " + password);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
    }
}
通过反射,创建运行时类的对象

创建 类的对象:调用Class对象的newInstance()方法
要求:
1)类必须有一个无参数的构造器。
2)类的构造器的访问权限需要足够。
难道没有无参的构造器就不能创建对象了吗?不是!只要在操作的时候明确的调用类中的构造器,并将参数传递进去之后,才可以实例化操作。
步骤如下:
1)通过Class类的getDeclaredConstructor(Class … parameterTypes)取得本类的指定形参类型的构造器
2)向构造器的形参中传递一个对象数组进去,里面包含了构造器中所需的各个参数。
3)通过Constructor实例化对象。

public class Test7 {
    public static void main(String[] args) {
        Class clazz = User.class;
        try {
            //调用此方法 创建运行时对象
            //要求 必须有空参函数构造器
            //设置为 public
            User user = (User) clazz.newInstance();

            System.out.println(user);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } finally {
        }
    }
}
举例体会反射的动态性

在运行时期才知道创建那个对象

提供结构丰富 Person 类
@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD,ElementType.PARAMETER,ElementType.CONSTRUCTOR,ElementType.LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnoTest {
    String value() default "hello";
}
public interface MyInte {
    void sayHello();
}
public class Person<T> implements Serializable {
    private static final long serialVersionUID = 1L;

    private char gender;
   public double weight;

    public void breath(){
        System.out.println("呼吸");
    }
    public void eat(){
        System.out.println("吃东西");
    }
}
@MyAnnoTest("xixixi")
public class User<T> extends Person<String> implements Serializable, Comparator<String> ,MyInte{
    private static final long serialVersionUID = 1L;
    private String name;
    private String email;
    private String phone;
    private String password;
    private int age;
    private double price;
    int haha;
    public int id;

    @MyAnnoTest("构造器方法")
    public User(String name, String email, String phone){
        this.name = name;
        this.email = email;
        this.phone = phone;
    }
    public User(String name, String email, String phone, String password, int age, double price) {
        this.name = name;
        this.email = email;
        this.phone = phone;
        this.password = password;
        this.age = age;
        this.price = price;

    }

    public User() {
    }

    private User(String name){
        this.name = name;
    }

    private User(String name,String email){
        throw new Error("此处不可以创建对象,死了这条心吧");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public int compare(String o1, String o2) {
        return 0;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o){
            return true;
        }
        if (o == null || getClass() != o.getClass()){
            return false;
        }
        User user = (User) o;
        return age == user.age &&
                Double.compare(user.price, price) == 0 &&
                Objects.equals(name, user.name) &&
                Objects.equals(email, user.email) &&
                Objects.equals(phone, user.phone) &&
                Objects.equals(password, user.password);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, email, phone, password, age, price);
    }


    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", phone='" + phone + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                ", price=" + price +
                '}';
    }

    public void show() {
        System.out.println("User.show");
    }

    private void privateShow() {
        System.out.println("User.privateShow");
    }

    @MyAnnoTest("方法上sayhello")
    @Override
    public void sayHello() {
        System.out.println("User.sayHello");
    }
}
反射可以做的

获取 Field 、Method 、Constructor 、Superclass 、Interface 、Annotation
 实现的全部接口
 所继承的父类
 全部的构造器
 全部的方法
 全部的Field

获取运行时类的属性结构及其内部结构
public class Test8 {
    public static void main(String[] args) {
        test1();
    }

    public static void test1(){
        /**
         * 获取所有属性
         * 可以获取 父类以及本类的共有(public)属性
         */
        Class clazz = User.class;
        Field[] fields = clazz.getFields();
        for (Field field : fields){
            System.out.println(field);
        }
        System.out.println();
        /**
         * 找出本类所有的属性 不能获取父类
         */
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field field : declaredFields) {
            System.out.println(field);
        }
        System.out.println();
        /**
         * 获取权限修饰符
         * 0 默认
         * 1 public
         * 2 private
         * 3 protected
         */
        for (Field field : declaredFields) {
            //1.权限修饰
            System.out.println(field.getModifiers());
            //2.数据类型
            System.out.println(field.getType());
            //3.变量名字
            System.out.println(field.getName());
        }
    }
}
获取运行时类的方法结构
public class Test8 {
    public static void main(String[] args) {
       test1();

    }
  public static void test1() {
        /**
         * 获取所有属性
         * 可以获取 父类以及本类的共有(public)属性
         */
        Class clazz = User.class;
        Field[] fields = clazz.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println();
        /**
         * 找出本类所有的属性 不能获取父类
         */
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field field : declaredFields) {
            System.out.println(field);
        }
        System.out.println();
        /**
         * 获取权限修饰符
         * 0 默认
         * 1 public
         * 2 private
         * 3 protected
         */
        for (Field field : declaredFields) {
            //1.权限修饰
            System.out.println(field.getModifiers());
            //2.数据类型
            System.out.println(field.getType());
            //3.变量名字
            System.out.println(field.getName());
        }
    }
}
获取运行时类的方法的内部结构
public class Test8 {
    public static void main(String[] args) {
       test2();

    }

    public static void test2() {
        /**
         * 获取运行时期的方法结构
         */

        /**
         * 获取当前类 包含私有 但是不包含父类
         */
        Class clazz = User.class;
        Method[] method1 = clazz.getDeclaredMethods();
        for (Method m : method1) {
            System.out.println(m);
            //2.获取所有方法返回值类型
            System.out.println(m.getReturnType());
            //3.获取所有方法的名字
            System.out.println(m.getName());
            //4.权限修饰符
            System.out.println(m.getModifiers());
            //5.注解
            Annotation[] annos = m.getAnnotations();
            for (Annotation anno : annos) {
                System.out.println(anno);
            }
            //6.获取形参列表
            System.out.print("(");
            Class<?>[] parameterTypes = m.getParameterTypes();
            if (parameterTypes != null) {
                for (int i = 0; i < parameterTypes.length; i++) {
                    System.out.print(parameterTypes[i] + ",");
                    System.out.print(parameterTypes[i].getName());
                }

            }
            System.out.print(")");
            //7.抛出的异常
            Class<?>[] exceptionTypes = m.getExceptionTypes();
            if (!(exceptionTypes.length == 0 || exceptionTypes == null)) {
                System.out.print("throws");
                for (int i = 0; i < exceptionTypes.length; i++) {
                    System.out.print(exceptionTypes[i] + " ");
                }

            }
            System.out.println();
        }
        System.out.println();
        //0获取声明为 public的方法
        Method[] method = clazz.getMethods();
        for (Method m : method) {
            //1.获取所有的方法
            System.out.println(m);
        }
    }
}
获取运行时类的构造器结构
public class Test8 {
    public static void main(String[] args) {
        Class clazz = User.class;
        /**
         * 获取运行类中的 public 构造器
         */
        Constructor[] constructors = clazz.getConstructors();
        for (Constructor constructor : constructors){
            System.out.println(constructor);
        }
        /***
         * 所有构造器
         */
        Constructor[] constructors1 = clazz.getDeclaredConstructors();
        for (Constructor constructor : constructors1){
            System.out.println(constructor);
        }
    }
}
获取运行时类的父类及父类的泛型
public class Test8 {
    public static void main(String[] args) {
        Class clazz = User.class;
        /**
         * 获取运行类的父类和泛型
         */
        Class superclass = clazz.getSuperclass();
        System.out.println(superclass);

        /**
         * 获取带泛型的父类
         */
        Type genericSuperclass = clazz.getGenericSuperclass();
        System.out.println(genericSuperclass);
        ParameterizedType parameterizedType = (ParameterizedType)genericSuperclass;
        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
        for (int i = 0; i < actualTypeArguments.length;i++){
            System.out.println(actualTypeArguments[i]);
        }

    }
}
获取运行时类的接口、所在包、注解等
public class Test8 {
    public static void main(String[] args) {
        Class clazz = User.class;
        /**
         * 获取接口
         */
        Class[] interfaces = clazz.getInterfaces();
        for (int i = 0;i<interfaces.length;i++){
            System.out.println(interfaces[i]);
        }

        Class[] interfaces1 = clazz.getSuperclass().getInterfaces();
        System.out.println(interfaces1);

        /**
         * 获取包
         */
        Package aPackage = clazz.getPackage();
        System.out.println(aPackage);

        /**
         * 获取注解
         */
        Annotation[] annotations = clazz.getAnnotations();
        for (int i =0 ; i < annotations.length;i++){
            System.out.println(annotations[i]);
        }
    }
}
调用运行时类中的指定属性
public class Test8 {
    public static void main(String[] args) {
        Class clazz = User.class;
        /**
         * 调用指定的属性
         * 获取属性的值 设置属性的值
         */
        try {

            /**
             * 创建运行时对象
             * 不能设置私有的
             */
            User user = (User) clazz.newInstance();
            Field id = clazz.getField("id");
            id.set(user, 1231);
            System.out.println(user);

            System.out.println();
            /**
             * 获取私有的
             */
            Field name = clazz.getDeclaredField("name");
            //私有的需要设置时可访问的
            name.setAccessible(true);
            name.set(user,"haxi");
            System.out.println(user);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }

    }
}
调用运行时类中的指定方法
public class Test8 {
    public static void main(String[] args) {
        Class clazz = User.class;
        /**
         * 创建运行时对象
         */
        try {
            User user = (User) clazz.newInstance();
            /**
             * 获取指定方法
             */
            Method show = clazz.getMethod("show", String.class);
            //参数一 方法的调用者 方法的形参
            show.setAccessible(true);
            //执行
            String str = (String) show.invoke(user, "CH");
            System.out.println(str);

            Method showDes = clazz.getDeclaredMethod("showDes");
            showDes.setAccessible(true);
            showDes.invoke(User.class);


        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }

    }
}
调用运行时类中的指定构造器
public class Test8 {
    public static void main(String[] args) {
        Class clazz = User.class;
        /**
         * 调用构造器
         */
        try {
            //获取
            Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class, String.class, String.class);
            //设置可以访问
            declaredConstructor.setAccessible(true);
            //调用
            User user = (User) declaredConstructor.newInstance("1", "2", "3");
            System.out.println(user);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }

    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容