• Java反射学习笔记


    感谢慕课网Cedar老师的视频!

    https://www.imooc.com/learn/199

    Java-reflect专题

    Class类的使用

    1.在面向对象的世界里,万事万物皆对象。

    类是谁的对象呢??? 类是java.lang.Class类的实例对象

    代码实例:

    package com.cj.study.test1;
    
    public class ClassDemo1 {
    
        public static void main(String[] args) {
            //Foo的实例如何表示
            Foo foo = new Foo();
    
            //Foo这个类也是一个实例对象,Class类的实例对象,如何表示呢?
            //任何一个类都是Class的实例对象,这个实例对象有三种表示方式
    
            //第一种表示方式--->实际在告诉我们任何一个类都有一个隐含的静态成员变量
            Class c1 = Foo.class;
    
            //第二种表示方式--->已经知道该类的对象通过getClass方法
            Class c2 = foo.getClass();
    
            /*
             * 官网c1,c2表示了Foo类的类类型(class type)
             * 万事万物皆对象
             * 类也是对象,是Class类的实例对象
             * 这个对象我们称为该类的类类型
             */
    
            //不管c1 or c2都代表了Foo类的类类型,一个类只可能是Class类的一个实例对象
            System.out.println(c1 == c2); //打印结果:true
    
            //第三种表达方式
            Class c3 = null;
    
            try {
                c3 = Class.forName("com.cj.study.test1.Foo");
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            System.out.println(c2 == c3); //打印结果:true
    
            //我们完全可以通过类的类类型创建类的实例对象-->通过c1 or c2 or c3创建Foo类的实例对象
    
            try {
                Foo foo1 = (Foo)c3.newInstance(); //需要有无参构造器的方法
                foo1.print(); //打印输出:foo
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    class Foo {
    
        void print(){
            System.out.println("foo");
        }
    }

    Java类的加载机制

    Class.forName("类的全称")

    · 不仅表示了类的类类型,还代表了动态加载类

    · 编译时刻加载类是静态加载类、运行时刻加载类是动态加载类

    静态加载类示例:

    Word.java

    class Word {
        public void start(){
            System.out.println("word...start...");
        } 
    }

    Excel.java

    class Excel {
        public void start(){
            System.out.println("excel...start...");
        }
    }

    Office.java

    class Office {
        public static void main(String[] arg){
            if("word".equals(arg[0])){
                Word word = new Word();
                word.start();
            }
    
            if("excel".equals(arg[0])){
                Excel excel = new Excel();
                excel.start();
            }
        }  
    }

    通过终端窗口进行编译并执行:

      终端输入:javac Office.java 进行编译会报错,找不到Word和Excel类,因为静态加载方式需要在编译时把类都进行加载

      如果想正确的输出需要先编译Word和Excel类,然后再编译Office.java!

    动态加载类示例:

    接口OfficeAble.java

    interface OfficeAble {
        public void start();
    }

    Word.java

    class Word implements OfficeAble{
        public void start(){
            System.out.println("word...start...");
        }
    }

    Excel.java

    class Excel implements OfficeAble{
        public void start(){
            System.out.println("excel...start...");
        }
    }

    Office.java

    class Office {
        public static void main(String[] arg){
            try{
                Class c = Class.forName(arg[0]);
                OfficeAble oa = (OfficeAble)c.newInstance();
                oa.start();
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }

    动态加载是在运行时进行加载,如果只编译OfficeAble,Word,Office,并且以Word作为入参进行输出是不会出错的,动态加载是在运行时需要什么就加载什么!

    方法的反射

    获取方法中常用信息

    package com.cj.study.test1;
    
    import java.lang.reflect.Method;
    
    public class ClassDemo2 {
    
        public static void main(String[] args) {
    
            Class<String> c1 = String.class;
    
            System.out.println(c1.getName());//打印结果:java.lang.String
            System.out.println(c1.getSimpleName());//打印结果:String
    
            printClassMessage("str");
    
        }
    
        /**
         * 打印类的信息,包括类的成员函数
         * @param obj
         */
        public static void printClassMessage(Object obj){
            //要获取类的信息,首先要获取类的类类型
            Class c = obj.getClass();
            //获取类的名称
            System.out.println("类的名称是:" + c.getName());
    
            /**
             * Method类,方法对象
             * 一个成员方法就是一个Method对象
             * getMethods()方法获取的是所有public的函数,包括父类继承而来的
             * getDeclaredMethods()获取的是所有该类自己声明的方法,不问访问权限
             */
            Method[] ms = c.getMethods();
            Method[] dm = c.getDeclaredMethods();
            for (Method m : ms) {
                //得到方法的返回值类型的类类型
                Class<?> returnType = m.getReturnType();
                System.out.println(returnType.getName() + " ");
                //得到方法的名称
                System.out.print(m.getName() + "(");
                //获取参数类型--得到的是参数列表的类型的类类型
                Class<?>[] parameterTypes = m.getParameterTypes();
                for (Class<?> parameterType : parameterTypes) {
                    System.out.print(parameterType.getName() + ",");
                }
                System.out.println(")");
            }
        }
    }
    printClassMessage调用打印结果:
    类的名称是:java.lang.String
    boolean 
    equals(java.lang.Object,)
    java.lang.String 
    toString()
    int 
    hashCode()
    int 
    compareTo(java.lang.Object,)
    int 
    compareTo(java.lang.String,)
    int 
    indexOf(java.lang.String,int,)
    int 
    indexOf(int,)
    int 
    indexOf(java.lang.String,)
    int 
    indexOf(int,int,)
    java.lang.String 
    valueOf(char,)
    java.lang.String 
    valueOf(java.lang.Object,)
    java.lang.String 
    valueOf(boolean,)
    java.lang.String 
    valueOf([C,int,int,)
    java.lang.String 
    valueOf([C,)
    java.lang.String 
    valueOf(double,)
    java.lang.String 
    valueOf(float,)
    java.lang.String 
    valueOf(long,)
    java.lang.String 
    valueOf(int,)
    int 
    length()
    boolean 
    isEmpty()
    char 
    charAt(int,)
    int 
    codePointAt(int,)
    int 
    codePointBefore(int,)
    int 
    codePointCount(int,int,)
    int 
    offsetByCodePoints(int,int,)
    void 
    getChars(int,int,[C,int,)
    [B 
    getBytes()
    [B 
    getBytes(java.lang.String,)
    void 
    getBytes(int,int,[B,int,)
    [B 
    getBytes(java.nio.charset.Charset,)
    boolean 
    contentEquals(java.lang.StringBuffer,)
    boolean 
    contentEquals(java.lang.CharSequence,)
    boolean 
    equalsIgnoreCase(java.lang.String,)
    int 
    compareToIgnoreCase(java.lang.String,)
    boolean 
    regionMatches(int,java.lang.String,int,int,)
    boolean 
    regionMatches(boolean,int,java.lang.String,int,int,)
    boolean 
    startsWith(java.lang.String,)
    boolean 
    startsWith(java.lang.String,int,)
    boolean 
    endsWith(java.lang.String,)
    int 
    lastIndexOf(int,int,)
    int 
    lastIndexOf(java.lang.String,int,)
    int 
    lastIndexOf(int,)
    int 
    lastIndexOf(java.lang.String,)
    java.lang.String 
    substring(int,)
    java.lang.String 
    substring(int,int,)
    java.lang.CharSequence 
    subSequence(int,int,)
    java.lang.String 
    concat(java.lang.String,)
    java.lang.String 
    replace(char,char,)
    java.lang.String 
    replace(java.lang.CharSequence,java.lang.CharSequence,)
    boolean 
    matches(java.lang.String,)
    boolean 
    contains(java.lang.CharSequence,)
    java.lang.String 
    replaceFirst(java.lang.String,java.lang.String,)
    java.lang.String 
    replaceAll(java.lang.String,java.lang.String,)
    [Ljava.lang.String; 
    split(java.lang.String,int,)
    [Ljava.lang.String; 
    split(java.lang.String,)
    java.lang.String 
    join(java.lang.CharSequence,[Ljava.lang.CharSequence;,)
    java.lang.String 
    join(java.lang.CharSequence,java.lang.Iterable,)
    java.lang.String 
    toLowerCase(java.util.Locale,)
    java.lang.String 
    toLowerCase()
    java.lang.String 
    toUpperCase()
    java.lang.String 
    toUpperCase(java.util.Locale,)
    java.lang.String 
    trim()
    [C 
    toCharArray()
    java.lang.String 
    format(java.util.Locale,java.lang.String,[Ljava.lang.Object;,)
    java.lang.String 
    format(java.lang.String,[Ljava.lang.Object;,)
    java.lang.String 
    copyValueOf([C,int,int,)
    java.lang.String 
    copyValueOf([C,)
    java.lang.String 
    intern()
    void 
    wait(long,int,)
    void 
    wait(long,)
    void 
    wait()
    java.lang.Class 
    getClass()
    void 
    notify()
    void 
    notifyAll()
    java.util.stream.IntStream 
    chars()
    java.util.stream.IntStream 
    codePoints()
     

    成员变量的反射

    package com.cj.study.test1;
    
    import java.lang.reflect.Field;
    
    public class ClassDemo3 {
        public static void main(String[] args) {
    //        printFieldMessage("hello");
            printFieldMessage(new Integer(1));
        }
        public static void printFieldMessage(Object obj){
            Class c = obj.getClass();
    
            /**
             * 成员变量也是对象
             * java.lang.reflect.Field
             * Field类封装了关于成员变量的操作
             * getFields()方法获取的是所有的public的成员变量的信息,包括父类继承的
             * getDeclaredFields()获取的是该类自己声明的成员变量的信息
             */
    //        Field[] fs = c.getFields();
            Field[] fs = c.getDeclaredFields();
            for (Field f : fs) {
                Class<?> type = f.getType();
                String typeName = type.getName();
                //得到成员变量的名称
                String fieldName = f.getName();
                System.out.println(typeName + "," + fieldName);
            }
        }
    }
    printFieldMessage调用打印结果:
    int,MIN_VALUE
    int,MAX_VALUE
    java.lang.Class,TYPE
    [C,digits
    [C,DigitTens
    [C,DigitOnes
    [I,sizeTable
    int,value
    int,SIZE
    int,BYTES
    long,serialVersionUID

    构造函数的反射

    package com.cj.study.test1;
    
    import java.lang.reflect.Constructor;
    
    public class ClassDemo4 {
    
        public static void main(String[] args) {
    //        printConMessage("hello");
            printConMessage(new Integer(1));
        }
    
        public static void printConMessage(Object obj){
            Class c = obj.getClass();
            /**
             * 构造函数也是对象
             * java.lang.Constructor中封装了构造函数的信息
             * getConstructors()获取所有本类声明的public构造函数
             * getDeclaredConstructors()得到本类声明的所有构造函数
             */
            Constructor[] cs = c.getConstructors();
    //        Constructor[] cs = c.getDeclaredConstructors();
            for (Constructor constructor : cs) {
                System.out.print(constructor.getName() + "(");
                Class[] parameterTypes = constructor.getParameterTypes();
                for (Class parameterType : parameterTypes) {
                    System.out.print(parameterType.getName() + ",");
                }
                System.out.println(")");
            }
        }
    }
    printConMessage调用打印结果:
    java.lang.Integer(int,)
    java.lang.Integer(java.lang.String,)

    通过类的类类型还可以获取很多关于类的信息,不一一列举了

     方法反射的基本操作

    package com.cj.study.test1;
    
    import java.lang.reflect.Method;
    
    public class MethodDemo1 {
        public static void main(String[] args) throws Exception {
            //要获取print(int,int)方法
            //1.要获取一个方法就是获取类的信息,获取类的信息首先要获取类的类类型
            A a = new A();
            Class c = a.getClass();
    /** * 2.获取方法名称和参数列表来决定 * getMethod获取的是public的方法 * getDeclaredMethod获取自己生命的方法 */ // Method m = c.getMethod("print", int.class, int.class); Method m = c.getDeclaredMethod("print", new Class[]{int.class,int.class}); //下方这样的调用方法和a.print(10,20)效果是一样的 //方法如果没有返回值返回null,有返回值就会返回具体的值 // Object o = m.invoke(a, new Object[]{10, 20}); Object o = m.invoke(a,10,20); Method m1 = c.getMethod("print"); Object o1 = m1.invoke(a); Method m2 = c.getMethod("print", new Class[]{String.class, String.class}); Object o3 = m2.invoke(a, new Object[]{"HELLO", "world"}); } } class A { public void print(int a, int b){ System.out.println(a + b); }; public void print(String a, String b){ System.out.println(a.toLowerCase() + " " + b.toUpperCase()); }; public void print(){ System.out.println("啥也没有"); }; }
    控制台打印结果:
    30
    啥也没有
    hello WORLD

    通过反射了解集合泛型的本质

    package com.cj.study.test1;
    
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    
    public class MethodDemo4 {
    
        public static void main(String[] args) {
            ArrayList list1 = new ArrayList();
    
            ArrayList<String> list2 = new ArrayList<String>();
            list2.add("hello");
    
            Class c1 = list1.getClass();
            Class c2 = list2.getClass();
    
            System.out.println(c1 == c2); //打印输出true
            //反射的操作都是编译之后的操作
    
            /**
             * c1 == c2结果返回true说明编译之后集合的泛型是去泛型化的
             * Java中集合的泛型是防止错误输入的,只在编译阶段有效,绕过就无效了
             *
             * 验证:我们可以操作方法的反射绕过编译
             */
    
            try {
                Method m = c2.getMethod("add",Object.class);
                m.invoke(list2,20); //绕过操作就绕过了泛型
                System.out.println(list2.size()); //打印输出2
    
                //不能使用加强for循环遍历,会报转换异常
    //            for (String s : list2) {
    //                System.out.println(s);
    //            }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
  • 相关阅读:
    7、python数据类型之集合set
    python基本数据类型练习
    matplotlib
    numpy常用函数
    pillow包
    keras-tensorflow版本对应
    python-激活和切换运行环境
    端口监控
    numpy
    低风险创业笔记
  • 原文地址:https://www.cnblogs.com/cuijiade/p/11743882.html
Copyright © 2020-2023  润新知