【java进阶12: 反射】获取类的字节码的三种方式、获取文件绝对路径(包括以流的方式返回)、资源绑定器、可变长度参数、反射调用对象方法、获取某个类的父类/实现的接口

本文详细介绍了Java中的反射机制,包括如何通过Class.forName()获取类的字节码,使用反射创建对象,操作类的属性、方法和构造函数。同时,讨论了类加载器的工作原理,以及如何通过反射灵活地实例化不同对象,强调了反射在框架开发中的重要性。
摘要由CSDN通过智能技术生成

反射

  1. 反射机制有什么用?

    通过java语言中的反射机制可以操作字节码文件。有点类似于黑客(可以读和修改字节码文件)

    通过反射机制可以操作代码片段。(class文件)

  2. 反射机制的相关类在哪个报下?

    java.lang.reflect.*;

  3. 反射机制相关的重要的类有哪些?

    //java.lang.Class :代表整个字节码,代表一个类型,代表整个类
    //java.lang.reflect.Method:代表字节码中的方法字节码,代表类中的方法
    //java.lang.reflect.Constructor :代表字节码中的构造方法字节码,代表类中的构造方法
    //java.lang.reflect.Field	:代表字节码中的属性字节码,代表类中的成员变量(静态变量+实例变量)
        
    //class
    public class User{
        //Field
    	int no;
        //Constructor
    	public User(){
    	
    	}
        //Method
    	public int getNo(){
    		return no;
    	}
    	public void setNo(int no){
    		this.no = no;
    	}
    }
    
  4. 获取类的字节码的三种方式

    字节码内存图

    在这里插入图片描述

    package reflect;
    
    import java.util.Date;
    
    /*
        要操作一个类的字节码,需要首先获取到这个类的字节码,怎么获取java.lang.Class实例?
            三种方式
                第一种:Class c = Class.forName("带有包名的完整类名");
                第二种:class c = 对象.getClass();
                第三种: Class c = 任何类型.class;
     */
    public class ReflectText01 {
        public static void main(String[] args) {
            /*
                Class.forName()
                1、静态方法
                2、方法的参数是一个字符串
                3、字符串需要的是一个完整类名
                4、完整类名必须带有包名、java.lang包也不能省略
             */
            Class c1 = null;
            Class c2 = null;
            try {
                c1 =Class.forName("java.lang.String");    //c1代表String.class 文件,或者说c1代表String类型
                c2 =Class.forName("java.util.Date");    //c2代表Data类型
                Class c3 =Class.forName("java.lang.Integer");   //c3代表Integer类型
                Class c4 =Class.forName("java.lang.System");    //c4代表System类型
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
    
            //java中任何一个对象都有一个方法:getClass()
            String s = "abc";
            Class x = s.getClass(); //x代表String.class字节码文件,x代表String类型
            System.out.println(c1 == x);    //true(==判断的是对象的内存地址)
    
            Date time = new Date();
            Class y = time.getClass();
            System.out.println(c2 == y);    //true(c2和y两个变量中保存的内存地址都是一样的,都指向方法区中的字节码文件)
    
            //第三种方式,java语言中任何一种类型,包括基本数据类型,都有.class类型
            Class z = String.class; //z代表String类型
            Class a = Date.class;   //a代表Date类型
            Class b = int.class;    //b代表int类型
            Class c = double.class; //c代表double类型
    
            System.out.println(x == z); //true
            System.out.println(y == a); //true
    
    
        }
    }
    
    
  5. 获取到Class,用newInstance()方法实例化对象

    User类

    package bean;
    
    public class User {
        public User(){
            System.out.println("无参数构造方法执行了");
        }
    }
    

    测试类

    package reflect;
    
    import bean.User;
    
    /*
        获取到Class,可以干什么?
            通过Class的newInstance()方法来实例化对象
            注意:newInstance()方法的内部实际上调用了无参数构造方法,必须保证无参数构造方法存在才行
     */
    public class ReflectText02 {
        public static void main(String[] args) {
    
            //这是不使用反射机制,创建对象
            User user =new User();
            System.out.println(user);
    
            //使用反射机制的方式创建对象
            try {
                //通过反射机制,获取Class,通过Class来实例化对象
                Class c =Class.forName("bean.User");//c代表User类型
    
                //newInstance() 这个方法会调用User这个类的无参构造方法,完成对象的创建
                //重点是:newInstance()这个方法调用的是无参构造,必须保证无参构造方法是存在的
                Object obj =c.newInstance();
    
                System.out.println(obj);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
        }
    }
    
  6. 验证反射机制的灵活性

    package reflect;
    
    import bean.User;
    import java.io.FileReader;
    import java.util.Properties;
    
    /*
        验证反射机制的灵活性
            java代码写一遍,在不改变java源代码的基础上,可以做到不同对象的实例化。非常灵活
            (符合OCP开闭原则:对扩展开放,对修改关闭。)
    
        后期要学习的是高级框架,而工作过程中,也都是使用高级框架,包括:ssh ssm
            Spring SpringMVC MyBatis
            Spring Struts Hibernate
            ···
            这些高级框架底层实现原理:都采用了反射机制。所以反射机制还是重要的
            学了反射机制有利于理解剖析框架底层的源代码
    
     */
    public class ReflectText03 {
        public static void main(String[] args) throws Exception {
            //这种方式代码就写死了
            User user = new User();
    
            //以下代码是灵活的,代码不需要改动,可以修改配置文件,配置文件修改之后,可以创建出不同的实例对象
            //通过IO流读取classinfo.properties文件
            FileReader reader = new FileReader("REFLECT\\classinfo.properties");
            //创建属性类对象
            Properties pro = new Properties();  //key 和 value 都是String类型
            //加载
            pro.load(reader);
            //关闭流
            reader.close();
    
            //通过key获取value
            String className = pro.getProperty("className");
            System.out.println(className);
            //通过反射机制实例化对象
            Class c =Class.forName(className);
            Object obj =c.newInstance();
            System.out.println(obj);
    
    
        }
    }
    

    classinfo配置文件

    className =java.util.Date
                #bean.User
    
  7. Class.forName()方法的执行会导致类加载

    package reflect;
    
    /*
        研究一下:Class.forName()发生了什么
            重点:
                如果你只是希望一个类的静态代码块执行,其他代码一律不执行。
                可以使用:Class.forName("带包名的完整类名")
                这个方法的执行会导致类加载,类加载时:静态代码块执行.
    
        提示:
            后面JDBC的时候,需要使用。
     */
    public class ReflectText04 {
        public static void main(String[] args) {
            try {
                //Class.forName()这个方法的执行会导致:类加载。
                Class.forName("reflect.MyClass");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
    
    class MyClass{
        //静态代码块在类加载的时候执行,并且只执行一次。
        static {
            System.out.println("MyClass类的静态代码块执行了");
        }
    }
    
  8. 获取一个文件的绝对路径

    package reflect;
    
    import java.io.FileReader;
    
    /*
        研究一下文件路径的问题
            怎么获取一个文件的绝对路径,以下讲解的这种方式是通用的。但前提是:文件需要在类路径下,才可以使用。
     */
    public class AboutPath {
        public static void main(String[] args) {
            //这种方式的路径缺点:移植性差,在IDEA默认的当前路径是project的根
            //这个代码假设离开了IDEA,到了其他位置,可能当前路径就不是project的根了,这个时候路径就无效了
            //FileReader reader = new FileReader("REFLECT\\classinfo.properties");
    
            //接下来说一种比较常用的方法,即使代码换位置了,这样编写依然是通用的
            //注意:使用以下通用方式的前提是:这个文件必须在类路径下
            //类路径:凡是在src下的都是在类路径下【记住】 。src是类的根路径
            /*
                解析:
                    Thread.currentThread()      当前线程对象
                    getContextClassLoader()     是线程对象的方法,可以获取到当前线程的类加载器对象
                    getResource()           【获取资源】这是类加载器对象的方法,当前线程的类加载器默认从类的根路径加载资源
                                            ("")里写入需要加载的文件名
                    getPath()           获取路径的方法
             */
            String path = Thread.currentThread().getContextClassLoader()
                    .getResource("classinfo2.properties").getPath();//这种方式获取文件绝对路径是通用的
            //采用以上代码可以拿到一个问文件绝对路径
            //  /D:/Program%20Files%20(x86)/IntelliJ%20IDEA%202019.3.3/javaSE/out/production/REFLECT/classinfo2.properties
            System.out.println(path);
    
            //获取dp.properties文件的绝对路径(从类的根路径下作为起点开始)
            String path2 =Thread.currentThread().getContextClassLoader().
                    getResource("bean/dp.properties").getPath();
            System.out.println(path2);
            //  /D:/Program%20Files%20(x86)/IntelliJ%20IDEA%202019.3.3/javaSE/out/production/REFLECT/bean/dp.properties
    
        }
    }
    
  9. 获取文件路径后,传入FileReader中。如何用流的方式返回

    package reflect;
    
    
    import java.io.File;
    import java.io.FileReader;
    import java.io.InputStream;
    import java.util.Properties;
    
    public class IoPropertiesText {
        public static void main(String[] args) throws Exception {
            //获取一个文件的绝对路径
            //如果你们路径有空格和汉字,要在getPath()前面加个toURI()
    /*        String path = Thread.currentThread().getContextClassLoader().getResource("classinfo2.properties").toURI().getPath();
            FileReader reader = new FileReader(path);*/
    
            //以流的方式返回
            InputStream reader = Thread.currentThread().getContextClassLoader().getResourceAsStream("classinfo2.properties");
    
            Properties pro = new Properties();
            pro.load(reader);
            reader.close();
    
            //通过key获取value
            String className = pro.getProperty("className");
            System.out.println(className);
    
        }
    }
    
  10. 以流的形式返回文件路径

    package reflect;
    
    import java.io.File;
    import java.io.FileReader;
    import java.io.InputStream;
    import java.util.Properties;
    
    public class IoPropertiesText {
        public static void main(String[] args) throws Exception {
            //获取一个文件的绝对路径
            //如果你们路径有空格和汉字,要在getPath()前面加个toURI()
    /*        String path = Thread.currentThread().getContextClassLoader().getResource("classinfo2.properties").toURI().getPath();
            FileReader reader = new FileReader(path);*/
    
            //以流的方式返回
            InputStream reader = Thread.currentThread().getContextClassLoader().getResourceAsStream("classinfo2.properties");
            System.out.println(reader);
    
            Properties pro = new Properties();
            pro.load(reader);
            reader.close();
    
            //通过key获取value
            String className = pro.getProperty("className");
            System.out.println(className);
    
        }
    }
    

    classinfo2.properties

    className =java.util.String
                #bean.User
    
  11. 资源绑定器

    package reflect;
    
    import java.util.ResourceBundle;
    
    /*
        java.util包下提供了一个资源绑定器,便于获取属性配置文件中的内容。
        根据一下这种方式的时候,属性配置文件xxx.properties必须放到类路径下
     */
    public class ResourceBundleText {
        public static void main(String[] args) {
            //资源绑定器,只能绑定xxx.properties文件,并且这个文件必须在类路径文件下,文件扩展名也必须是properties
            //并且在写路径的时候,路径后面的扩展名不能写
            ResourceBundle bundle = ResourceBundle.getBundle("classinfo2");
    
            String className = bundle.getString("className");
            System.out.println(className);
        }
    }
    
  12. 关于JDK中自带的类加载器:

    • 什么是类加载器?

      专门负责加载类的命令/工具

      ClassLoader

    • JDK中自带了三个类加载器

      启动类加载器(父加载器):rt.jar

      扩展类加载器(母加载器):ext/*.jar

      应用类加载器:classpath

    • 假设有这样一段代码

      String s = "abc";
      

      代码在开始执行之前,会将所需要类全部加载到JVM当中。通过类加载器加载,看到以上代码类加载会找String.class文件,找到就加载,那么是怎么进行加载的呢?

      ​ 首先通过“启动类加载器”加载。

      ​ 注意:启动类加载器专门加载:C:\Program Files\Java\jdk1.8.0_221\jre\lib\rt.jar

      ​ rt.jar中都是JDK最核心的类库。

      ​ 如果通过“启动类加载器”加载不到的时候,会通过“扩展类加载器”加载

      ​ 注意:扩展类加载器专门加载:C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext*.jar

      ​ 如果“扩展类加载器”没有加载到,那么会通过“应用类加载器”加载。

      ​ 注意:应用类加载器专门加载:classpath中的jar包(class文件)

    • java中为了保证类加载的安全,使用了双亲委派机制。

      优先从”启动类加载器“中加载,这个称为“父”

      “父”无法加载到,再从“扩展类加载器”中加载,这个称为“母”

      双亲委派,如果都加载不到,才会考虑从应用类加载器中加载。直到加载到为止

  13. 反射属性

    package bean;
    
    //反射属性Field
    public class Student {
        //Field翻译为字段,其实就是属性/成员
        //4个Field,分别采用了不同的访问控制权限修饰符
        public int no;  //Field对象
        private String name;
        protected int age;
        boolean sex;
        public static final double MATH_PI = 3.1415926;
    
    }
    

    反射属性的方法

    package reflect;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.Modifier;
    
    /*
    反射属性Field
     */
    public class ReflectText05 {
        public static void main(String[] args) throws Exception{
            //获取整个类
            Class studentClass = Class.forName("bean.Student");
            System.out.println("完整类名:"+studentClass.getName()); //bean.Student
            System.out.println("简类名:"+studentClass.getSimpleName()); //Student
    
            //获取类中所有的public修饰的Field
            Field[] fields = studentClass.getFields();
            System.out.println(fields.length);
    
            //取出这个field
            Field f = fields[0];
            //取出这个field的名字
            System.out.println(f.getName());
    
            //获取所有的field
            Field[] fs = studentClass.getDeclaredFields();
            System.out.println(fs.length);
            System.out.println("---------------------------");
            for(Field field : fs){
                //获取属性的修饰符列表
                System.out.println(field.getModifiers());
                //将这个代号转换为字符串   调用Modifier.toString()方法
                System.out.println(Modifier.toString(field.getModifiers()));
                //获取属性的类型
                //System.out.println(field.getType());    //class类型的
                System.out.println(field.getType().getSimpleName());    //获取简称的类名
                //获取属性的名字
                System.out.println(field.getName());
            }
        }
    }
    

    反编译Student类(了解)

    package reflect;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.Modifier;
    
    /*
        反编译Student
     */
    public class ReflectText06 {
        public static void main(String[] args) throws Exception{
            //创建这个是为了拼接字符串
            StringBuilder s = new StringBuilder();
    
            Class studentClass = Class.forName("bean.Student");//bean.Student
    
            s.append(Modifier.toString(studentClass.getModifiers())+" class "+studentClass.getSimpleName()+"{\n");
            Field[] fields = studentClass.getDeclaredFields();
            for(Field field :fields){
                s.append("\t");
                s.append(Modifier.toString(field.getModifiers()));
                //如果有访问控制权限修饰符修饰的话,才会加:空格。如果没有则不会加
                if ((field.getModifiers())!= 0){
                    s.append(" ");
                }
                s.append(field.getType().getSimpleName());
                s.append(" ");
                s.append(field.getName());
                s.append(";\n");
            }
    
            s.append("}");
            System.out.println(s);
        }
    
    }
    
  14. 通过反射机制访问一个java对象的属性(重点)

    package reflect;
    
    import bean.Student;
    
    import java.lang.reflect.Field;
    
    /*
    必须掌握:
        怎么通过反射机制访问一个java对象的属性?
            给属性赋值:set
            获取属性的值:get
     */
    public class ReflectText07 {
        public static void main(String[] args) throws Exception{
            //不使用反射机制,怎么访问一个对象的属性?
                Student s = new Student();
                //赋值
                s.no = 1111;    //三要素:给s对象的no属性赋值1111
                                //要素1:对象s
                                //要素2:no属性
                                //要素3:1111
                //读取属性的值
                //两个要素:获取s对象no属性的值
                System.out.println(s.no);
    
            //使用反射机制,怎么去访问一个对象的属性。(set、get)
            Class studentClass = Class.forName("bean.Student");
            Object obj = studentClass.newInstance();    //obj底层就是student对象(底层调用无参构造方法)
    
            //获取no属性(根据属性的名称来获取Field)
            Field noField = studentClass.getDeclaredField("no");
    
            //给obj对象(Student对象)的no属性赋值
            /*
                虽然使用了反射机制,但三要素还是缺一不可:
                    要素1:obj对象   要素2:no属性    要素3:赋值2222
                注意:
                    反射机制虽然让代码更复杂了,但是为了“灵活”,都是值得的
             */
            noField.set(obj,2222);
    
            //读属性的值
            //两个要素:获取obj对象的no属性的值
            System.out.println(noField.get(obj));
    
    
            //可以访问私有的属性吗?
            Field nameField = studentClass.getDeclaredField("name");
            //需要打破封装,才能访问(反射机制的缺点:打破封装,可能会给不法分子留下机会!!)
            //调用方法打破封装后,在外部也可以访问private修饰的属性。
            nameField.setAccessible(true);
            //赋值
            nameField.set(obj,"jack");
            //获取
            System.out.println(nameField.get(obj));
    
        }
    }
    
  15. 可变长度参数

    package reflect;
    
    /*
        可变长度参数:
            int... ages :这就是可变长度参数
            语法:类型...    (注意:一定是3个.)
    
            1、可变长度参数要求的参数个数是:0~n个。
            2、可变长度参数在参数列表中必须在最后一个位置上,而且可变长度参数只能有一个。
            3、可变长度参数可以当作一个数组来看待
    
     */
    public class ArgsText {
        public static void main(String[] args) {
            m();
            m(1);
            m(1,1);
    
            //编译报错
            //m("abc");
    
            s(1);
            s(1,"s");
            s(2,"kdd","dkf");
    
            array("ab","d","dbg","dk","kdf");
            String[] strings = {"aa","bb","cc"};
            //也可以传一个数组
            array(strings);
    
            //直接传一个数组
            array(new String[]{"我","是","中","国","人"});
    
            //可以传数组,但没必要
            array("我","是","中","国","人");
    
    
        }
        public static void m(int... ages){
            System.out.println("m方法执行了");
        }
    
        //可变长度参数在参数列表中必须在最后一个位置上,而且可变长度参数只能有一个。
        //public static void m2(String... names,int... ages){}
    
        //可变长度参数必须在最后
        public static void s(int i,String... names){
            System.out.println("ssss");
        }
    
        public static void array(String... nn){
            //nn有length属性,说明nn是一个数组
            //可以将可变长度参数当作一个数组看待
            for(int i = 0;i<nn.length;i++){
                System.out.println(nn[i]);
            }
        }
    }
    
  16. 反编译类的方法

    用户业务类

    package service;
    
    /*
        用户业务类
     */
    
    public class UserService {
        /**
         * 登录方法
         * @param name 用户方法
         * @param password 密码
         * @return  true表示:登陆成功     false:表示登陆失败
         */
        public boolean login(String name,String password){
            if("admin".equals(name) && "123".equals(password)){
                return true;
            }
            return false;
        }
    
        /**
         * 退出系统的方法
         */
        public void logout(){
            System.out.println("系统已经安全退出");
        }
    }
    

    反射Method

    package reflect;
    
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    
    /*
        了解:
            反射Method
     */
    public class ReflectText08 {
        public static void main(String[] args) throws Exception{
            //获取类
            Class userServiceClass = Class.forName("service.UserService");
            //获取所有Method(包括私有的)
            Method[] methods =userServiceClass.getDeclaredMethods();
    
            //遍历Method
            for(Method method :methods){
                //获取修饰符列表
                System.out.println(Modifier.toString(method.getModifiers()));
                //获取方法的返回值类型
                System.out.println(method.getReturnType().getSimpleName());
                //获取方法名
                System.out.println(method.getName());
                //方法的修饰符列表(一个方法的参数可能会有多个)
                Class[] parameterTypes =method.getParameterTypes();
                for(Class c : parameterTypes){
                    System.out.println(c.getSimpleName());
                }
            }
        }
    }
    

    反编译一个类的所有方法

    package reflect;
    
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    
    /*
        反编译一个类的方法
     */
    public class ReflectText09 {
        public static void main(String[] args) throws Exception{
            StringBuffer s = new StringBuffer();
            Class userServiceCLass = Class.forName("java.lang.String");//service.UserService
            s.append(Modifier.toString(userServiceCLass.getModifiers())+" class "+userServiceCLass.getSimpleName()+"{");
    
            Method[] methods = userServiceCLass.getDeclaredMethods();
            for(Method method :methods){
                s.append("\n\n\t");
                s.append(Modifier.toString(method.getModifiers()));
                if(method.getModifiers() != 0){
                    s.append(" ");
                }
                s.append(method.getReturnType().getSimpleName());
                s.append(" ");
                s.append(method.getName());
                s.append("(");
                //参数列表
                Class[] parameterTypes = method.getParameterTypes();
                for(Class para: parameterTypes){
                    s.append(para.getSimpleName());
                    s.append(",");
                }
                if(parameterTypes.length>1){
                    //删除指定下标位置上的字符
                    s.deleteCharAt(s.length()-1);
                }
                s.append("){}");
            }
    
            s.append("\n}");
            System.out.println(s);
        }
    }
    
  17. 通过反射机制调用一个对象的方法(重点)

    userSrevice

    package service;
    
    /*
        用户业务类
     */
    
    public class UserService {
        /**
         * 登录方法
         * @param name 用户方法
         * @param password 密码
         * @return  true表示:登陆成功     false:表示登陆失败
         */
        public boolean login(String name,String password){
            if("admin".equals(name) && "123".equals(password)){
                return true;
            }
            return false;
        }
        //可能还有一个同名login方法,java中区分一个方法:依靠方法名和参数列表
        public void login(int i){
    
        }
    
        /**
         * 退出系统的方法
         */
        public void logout(){
            System.out.println("系统已经安全退出");
        }
    }
    

    反射方法

    package reflect;
    
    import service.UserService;
    
    import java.lang.reflect.Method;
    
    /*
        重点:通过反射机制怎么调用一个对象的方法?
            重点
    
            反射机制,让代码具有通用性,可变化的内容都是写到配置文件当中
            将来修改配置文件之后,创建的对象不一样了,调用的方法也不同了,但是java代码不需要做任何改动。这就是反射机制的魅力
     */
    public class ReflectText10 {
        public static void main(String[] args) throws Exception{
            //不使用反射机制,怎么调用方法?
            UserService userService = new UserService();
            /*
                调用方法的四要素分析:
                    1、对象userService
                    2、login方法名
                    3、实参列表
                    4、返回值
             */
            boolean loginSuccess = userService.login("admin","123");
            System.out.println(loginSuccess?"登陆成功":"登陆失败");
    
            //使用反射机制来调用一个对象的方法应该怎么做?
            Class userServiceClass = Class.forName("service.UserService");
            //创建对象
            Object obj = userServiceClass.newInstance();
            //获取Method
            Method loginMethod = userServiceClass.getDeclaredMethod("login", String.class, String.class);
            //调用方法  也需要四要素。
            //反射机制中最重要的一个方法,必须记住
            //      返回值     方法              对象          实参列表
            Object retValue = loginMethod.invoke(obj,"admin","123");
            //loginMethod方法、obj对象、实参“admin”“123”、retValue返回值
            System.out.println(retValue);
        }
    }
    
  18. 反编译一个类的构造方法

    Vip类

    package bean;
    
    public class Vip {
            int no;
            String name;
            String birth;
            boolean sex;
    
        public Vip(int no, String name, String birth, boolean sex) {
            this.no = no;
            this.name = name;
            this.birth = birth;
            this.sex = sex;
        }
    
        public Vip(int no, String name, String birth) {
            this.no = no;
            this.name = name;
            this.birth = birth;
        }
    
        public Vip(int no, String name) {
            this.no = no;
            this.name = name;
        }
    
        public Vip() {
        }
    
        public Vip(int no) {
            this.no = no;
        }
    }
    

    反编译一个类的构造方法

    package reflect;
    
    /*
        反编译一个类的Constructor构造方法
     */
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Modifier;
    
    public class ReflectText11 {
        public static void main(String[] args) throws Exception{
            StringBuilder s = new StringBuilder();
            Class vipClass = Class.forName("java.lang.String");//bean.Vip
            s.append(Modifier.toString(vipClass.getModifiers()));
            s.append(" Class ");
            s.append(vipClass.getSimpleName());
            s.append("{");
    
            //拼接构造方法
            Constructor[] constructors = vipClass.getDeclaredConstructors();
            for(Constructor constructor :constructors){
                s.append("\n\n\t");
                s.append(Modifier.toString(constructor.getModifiers()));
                s.append(" ");
                s.append(vipClass.getSimpleName());
                s.append("(");
                //拼接参数
                Class[] parameterTypes = constructor.getParameterTypes();
                for(Class parameterType :parameterTypes){
                    s.append(parameterType.getSimpleName());
                    s.append(",");
                }
                //如果有参数,则删掉最后的,号,如果没有参数,则不删除
                if(parameterTypes.length >0){
                    s.deleteCharAt(s.length()-1);
                }
    
                s.append("){}");
            }
    
            s.append("}");
            System.out.println(s);
    
        }
    }
    
  19. 通过反射机制调用构造方法实例化java对象

    vip类

    package bean;
    
    public class Vip {
            int no;
            String name;
            String birth;
            boolean sex;
    
        public Vip(int no, String name, String birth, boolean sex) {
            this.no = no;
            this.name = name;
            this.birth = birth;
            this.sex = sex;
        }
    
        public Vip(int no, String name, String birth) {
            this.no = no;
            this.name = name;
            this.birth = birth;
        }
    
        public Vip(int no, String name) {
            this.no = no;
            this.name = name;
        }
    
        public Vip() {
        }
    
        public Vip(int no) {
            this.no = no;
        }
    
        @Override
        public String toString() {
            return "Vip{" +
                    "no=" + no +
                    ", name='" + name + '\'' +
                    ", birth='" + birth + '\'' +
                    ", sex=" + sex +
                    '}';
        }
    }
    

    实例化

    package reflect;
    
    import bean.Vip;
    
    import java.lang.reflect.Constructor;
    
    /*
        比上一个例子(11)重要一些
            通过反射机制调用构造方法实例化java对象
     */
    public class ReflectText12 {
        public static void main(String[] args) throws Exception{
            //不使用反射机制创建对象
            Vip v1 = new Vip();
            Vip v2 = new Vip(100,"zhangsan","2001-10-11",true);
    
            //使用反射机制创建对象
            Class vipClass = Class.forName("bean.Vip");
            //调用无参数的构造方法
            Object obj =vipClass.newInstance();
            System.out.println(obj);
            //调用有参数的构造方法怎么办?
            //第一步:先获取到这个有参数的构造方法
            Constructor con = vipClass.getDeclaredConstructor(int.class,String.class,String.class,boolean.class);
            //第二步:调用构造方法new对象
            Object newObj = con.newInstance(200,"lisi","1999-09-09",true);
            System.out.println(newObj);
    
            //获取无参数的构造方法
            Constructor con2 = vipClass.getDeclaredConstructor();
            Object newObj2 = con2.newInstance();
            System.out.println(newObj2);
    
        }
    }
    
  20. 重点:怎么获取一个类的父类/实现的接口

    package reflect;
    
    /*
        重点:怎么获取一个类的父类,以及实现的接口
     */
    public class ReflectText13 {
        public static void main(String[] args) throws Exception{
            //String类举例
            Class stringClass =Class.forName("java.lang.String");
    
            //获取String类的父类
            Class superClass =stringClass.getSuperclass();
            System.out.println(superClass.getName());
    
            //获取String类实现的所有接口(一个类可以实现多个接口)
            Class[] interfaces = stringClass.getInterfaces();
            for(Class face :interfaces){
                System.out.println(face.getName());
            }
        }
    }

     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值