zoukankan      html  css  js  c++  java
  • java入门篇9 --- 反射

    反射

    我们自己定义的class其实是JVM在运行时动态加载的,每读到一个class,JVM就会床架一个CLASS实例,并加载到内存中

    我们首先看一下Class的源码,从源码可以看出,在进行实例化时,它是一个私有方法,因此,我们写的java程序无法将其实例化,通过分析源码,我们可以确认,我们定义的每个类最终都是Class的实例,因此他们都指向数据类型class或者interface,Class里面有很多字段,因此每个Class的实例里面包含这个类所有的信息

    public final class Class<T> implements java.io.Serializable,
            GenericDeclaration,
            Type,
            AnnotatedElement,
            TypeDescriptor.OfField<java.lang.Class<?>>,
            Constable {
        private Class(ClassLoader loader, Class<?> arrayComponentType) {
            // Initialize final field for classLoader.  The initialization value of non-null
            // prevents future JIT optimizations from assuming this final field is null.
            classLoader = loader;
            componentType = arrayComponentType;
      ... } }
    public class HelloWorld {
        public static void main(String[] args) throws Exception {
            Class t = new Class(ClassLoader.getPlatformClassLoader(), String.class);  //java: Class(java.lang.ClassLoader,java.lang.Class<?>) 在 java.lang.Class 中是 private 访问控制
        }
    }

    接下来看一下我们反射调用,这个一般自己写框架时会用到

    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    
    class Person {
        public String name;
    
        public Person(String name) {
            this.name = name;
        }
        public void eat(){
            System.out.println("Person eat");
        }
        public String run(String s){
            return String.format("Person is running on %s", s);
        }
        public void nothing(){
        }
    }
    
    class Student extends Person {
        private String sex;
        public int age;
    
        public Student(String name, String sex, int age) {
            super(name);
            this.sex = sex;
            this.age = age;
        }
        @Override
        public void eat(){
            System.out.println("Student eat");
        }
        @Override
        public String run(String s){
            return String.format("Student is running on %s", s);
        }
        private void getSex(){
            System.out.println(this.sex);
        }
        public static void ss(){
            System.out.println("static");
        }
    }
    
    public class HelloWorld {
        public static void main(String[] args) throws Exception {
            // 获取string的Class实例
            Class c1 = String.class;
            Class c2 = "h".getClass();
            Class c3 = Class.forName("java.lang.String");
            // 因为Class实例是JVM中唯一的,都是String.class,因此可以使用 == 来进行比较
            System.out.println(c1 == c2);  // true  从结果分析,我们更可以断定,实例是唯一的
            System.out.println(c1 == c3);  // true
            // 我们以前用过 instanceof 来判断是否是可以向上转型
            Integer n = Integer.valueOf(1);
            System.out.println(n instanceof Number);  // true  因为Integer是Number的子类
            // System.out.println(n.getClass()  == Number.class);   // Error:(14, 42) java: 不可比较的类型: java.lang.Class<capture#1, 共 ? extends java.lang.Integer>和java.lang.Class<java.lang.Number>
            System.out.println("".getClass().getName());  // java.lang.String
            System.out.println("".getClass().getSimpleName()); // String
            System.out.println("".getClass().isInterface());  // false
            System.out.println("".getClass().isPrimitive());  // false
            System.out.println("".getClass().isArray());  // false
            Class stud = Student.class;
            // 获取字段,可以使用getField来获取指定字段,但是对于private字段,无法获取,需要使用getDeclaredField
            System.out.println(stud.getField("age"));  // public int Student.age
            System.out.println(stud.getField("name"));  // public java.lang.String Person.name
            System.out.println(stud.getDeclaredField("sex"));  // private java.lang.String Student.sex
            // System.out.println(stud.getField("sex"));  // Exception in thread "main" java.lang.NoSuchFieldException: sex
            // 使用getFields,来获取全部非privte字段
            Field[] f = stud.getFields();
            System.out.println("----");
            for (Field ff : f) {
                System.out.println(ff);
            }  // public int Student.age   public java.lang.String Person.name
            System.out.println("----");
            // 使用getDeclaredFields,来获取当前类全部字段
            Field[] f1 = stud.getDeclaredFields();
            for (Field ff1 : f1) {
                System.out.println(ff1);
            }  // private java.lang.String Student.sex  public int Student.age
            Field f2 = stud.getField("age");
            Field f3 = stud.getDeclaredField("sex");
            System.out.println(f2.getName());  // age 获取这个字段的名称
            System.out.println(f3.getName());  // name 获取这个字段的名称
            System.out.println(f2.getType());  // int 获取这个字段的类型
            System.out.println(f3.getType());  // class java.lang.String 获取这个字段的类型
            System.out.println(f2.getModifiers());  // 1  获取这个字段的修饰符 该字段修饰符是public,不同的int值代表不同
            System.out.println(f3.getModifiers());  // 2  获取这个字段的修饰符
            int ff2 = f2.getModifiers();
            System.out.println(Modifier.isFinal(ff2));  // false
            System.out.println(Modifier.isPrivate(ff2)); // false
            System.out.println(Modifier.isPublic(ff2));  // false
            // 获取字段的值
            Student s = new Student("ming", "male", 25);
            Class st = s.getClass();
            Field f4 = st.getDeclaredField("sex");
    //        Object v = f4.get(s);  // java.lang.IllegalAccessException: class HelloWorld cannot access a member of class Student with modifiers "private" 被阻止
            f4.setAccessible(true);  // 对于private字段,使用setAccessible(true),但是仍然有可能会报IllegalAccessException错误
            Object v = f4.get(s);
            System.out.println(v);  // male 获取字段的值
            // 重置字段的值
            Field f5 = st.getField("name");
            f5.set(s, "ning");
            f5.setAccessible(true);  // 对于private,都需要设置这个
            f4.set(s, "female");
            System.out.println(s.name);  // ning
            System.out.println(f4.get(s));  // female
            // 获取方法
            Class ss = Student.class;
            System.out.println(ss.getMethod("run", String.class)); // public java.lang.String Student.run(java.lang.String)
            System.out.println(ss.getMethod("eat"));  // public void Student.eat()
            // System.out.println(ss.getMethod("getSex"));  // 无法获取私有方法,java.lang.NoSuchMethodException: Student.getSex()
             System.out.println(ss.getDeclaredMethod("getSex"));  // private void Student.getSex()
            Method[] sm = ss.getMethods();
            Method[] sm1 = ss.getDeclaredMethods();
            System.out.println("---");
            for(Method smm : sm){
                System.out.println(smm);
            } //public java.lang.String Student.run(java.lang.String) public void Student.eat() public void Person.nothing() public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
    //        public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
    //        public final void java.lang.Object.wait() throws java.lang.InterruptedException
    //        public boolean java.lang.Object.equals(java.lang.Object)
    //        public java.lang.String java.lang.Object.toString()
    //        public native int java.lang.Object.hashCode()
    //        public final native java.lang.Class java.lang.Object.getClass()
    //        public final native void java.lang.Object.notify()
    //        public final native void java.lang.Object.notifyAll()
            System.out.println("---");
            // 无法获取父类的方法
            for(Method smm : sm1){
                System.out.println(smm);
            } // public java.lang.String Student.run(java.lang.String) public void Student.eat() private void Student.getSex()
    
            Method smm = ss.getMethod("run", String.class);
            Method smm1 = ss.getMethod("eat");
            // 获取方法名
            System.out.println(smm.getName());  // run
            System.out.println(smm1.getName());  // eat
            // 获取返回类型
            System.out.println(smm.getReturnType());  // class java.lang.String
            System.out.println(smm1.getReturnType());  // void
            // 获取参数数量
            System.out.println(smm.getParameterCount());  // 1
            System.out.println(smm1.getParameterCount()); // 0
    
            // 方法的调用
            System.out.println(smm.invoke(s, "floor")); // Student is running on floor
            smm1.invoke(s);  // Student eat
    //         Method smm2 = ss.getMethod("getSex"); // java.lang.IllegalArgumentException: object is not an instance of declaring class
            Method smm2 = ss.getDeclaredMethod("getSex");
            smm2.setAccessible(true);  // 如果不设置这个会报错,私有属性必须设置
            smm2.invoke(s); // female
            // 多态
            Method p = Person.class.getMethod("eat");
            p.invoke(s);  // Student eat 虽然方法是person的,但传入的实例属于Student,因此但因Student方法
            // 调用静态方法
            Method ssm = Student.class.getMethod("ss");
            ssm.invoke(null);  // static
    
            // 获取构造方法
            Constructor pp = Person.class.getConstructor(String.class);
            Person ppp = (Person) pp.newInstance("ming");
            System.out.println(ppp.name);  // ming
    
            // 获取继承关系
            Class s5 = Student.class;
            System.out.println(s5.getSuperclass());  // class Person
            System.out.println(s5.getSuperclass().getSuperclass()); // class java.lang.Object
            // 获取interface 值返回直接实现的
            Class[] s5i = s5.getInterfaces();
            System.out.println("---");
            for(Class s5s : s5i){
                System.out.println(s5s);
            }  //
            System.out.println("---");
            Class[] i5 = Integer.class.getInterfaces();
            for(Class i5s : i5){
                System.out.println(i5s);
            }  // interface java.lang.Comparable interface java.lang.constant.Constable interface java.lang.constant.ConstantDesc
        }
    
    }
  • 相关阅读:
    Beacon技术是什么?
    exclude kernel or other packages from getting updated
    (OK) running CORE & docker on Fedora 23 server
    (OK) dnf
    (OK) dnf
    rpm
    dnf
    dnf install -y kernel-4.2.3-300.fc23
    paper4—Multi-MPE_Trigger_Algorithm—testing
    paper4—Multi-MPE_Trigger_Algorithm
  • 原文地址:https://www.cnblogs.com/yangshixiong/p/12168857.html
Copyright © 2011-2022 走看看