分分1分快三网址_Java匹马行天下之JavaSE核心技术——反射机制

  • 时间:
  • 浏览:2
  • 来源:熊猫辅助网_提供洋葱娱乐网技术_梅花辅助网资讯

    在运行情況中,对于任意有三个 类,都都可不还可以获取到这俩类的所有属性和方式,对于任意有三个 对象,都都可不还可以调用它的任意有三个 方式和属性(包括私有的方式和属性),这俩动态获取的信息以及动态调用对象的方式的功能就称为java语言的反射机制。通俗点讲,通过反射,该类对大伙来说是完全透明的,想要获取任何东西都还可不还可以 。

    想要使用反射机制,就可不还可以 要先获取到该类的字节码文件对象(.class),通过字节码文件对象,就都可不还可以通过该类中的方式获取到大伙想要的所有信息(方式,属性,类名,父类名,实现的所有接口等等),每有三个 类对应着有三个 字节码文件也就对应着有三个 Class类型的对象,也而是字节码文件对象。

JAVA反射机制是在运行情況中,

  对于任意有三个 类,都都可不还可以知道这俩类的所有属性和方式(动态获取的信息);

  对于任意有三个 对象,都都可不还可以调用它的任意有三个 方式和属性(动态调用对象的方式);

  这俩动态获取的信息以及动态调用对象的方式的功能称为java语言的反射机制

  简言之:通过字节码文件对象,去使用该文件中的成员变量、构造方式、成员方式。

    获取字节码文件对象的一种 方式。

       1、Class class1 = Class.forName("全限定类名");  //通过Class类中的静态方式forName,直接获取到有三个 类的字节码文件对象,此时该类还是源文件阶段,并没能变为字节码文件。

       2、Class class2  = Person.class;    //当类被加载成.class文件时,此时Person类变成了.class,在获取该字节码文件对象,也而是获取被委托人, 该类居于字节码阶段。

       3、Person p = new Person();

                              Class class3 = p.getClass();    //通过类的实例获取该类的字节码文件对象,该类居于创建对象阶段 

第一种

和后一种

的区别        
        后一种

你可不还可以

明确Person类型。
        第一种

可不还可以

这俩类型的字符串就行(开发中用)。
        这俩扩展更强,不可不还可以

知道具体的类,只提供字符串,按照配置文件加载就还可不还可以

了。

 反射的特点:

        1.Class类中的静态方式forName()传入的字符串将来会做成配置信息文件,而是以前你我不知道多多系统进程 运行的是谁(是哪个类)        2.反射是不让看完类的任何信息的。即通过构造方式对象Constructor、成员方式对象Method,调用大伙的方式返回值就有Object类型。          (可能性任何类型都还可不还可以 用Object类型接收,基本数据类型会自动装箱为引用数据类型)。        3.反射还可不还可以 访问私有的东西(前提是class文件未被加密)。

一种 获取字节码文件对应的Class类型的对象的方式

  要想解剖有三个 类,可不还可以 没能获取到该类的字节码文件对象。

  而解剖使用的而是Class类中的方式,而是没能获取到每有三个 字节码文件对应的Class类型的对象。

  .class文件   --> Class类

    成员变量    --> Field类    构造方式    --> Constructor类    成员方式    --> Method类

    有了字节码文件对象可不还可以获得类中所有的信息,大伙在使用反射获取信息时,也要考虑使用后边哪种方式获取字节码对象合理,视不同情況而定。下面介绍Class类的功能。

实例一:

package com.my.fanshe;
 2 
 3 public class Person {
 4     private String name;
 5     int age;
 6     public String address;
 7 
 8     public Person() {
 9     }
10 
11     private Person(String name) {
12         this.name = name;
13     }
14 
15     Person(String name, int age) {
16         this.name = name;
17         this.age = age;
18     }
19 
20     public Person(String name, int age, String address) {
21         this.name = name;
22         this.age = age;
23         this.address = address;
24     }
25 
26     public void show() {
27         System.out.println("show");
28     }
29 
300     public void method(String s) {
31         System.out.println("method " + s);
32     }
33 
34     public String getString(String s, int i) {
35         return s + "---" + i;
36     }
37 
38     private void function() {
39         System.out.println("function");
40     }
41 
42     @Override
43     public String toString() {
44         return "Person [name=" + name + ", age=" + age + ", address=" + address + "]";
45     }
46 
47 }

package com.my.fanshe;


/* 4 * 反射:而是通过class文件对象,去使用该文件中的成员变量,构造方式,成员方式。 5 * 6 * Person p = new Person(); 7 * p.使用; 8 * 9 * 要想没能 使用,首先你可不还可以 得到class文件对象,着实也而是得到Class类的对象。 10 * .class文件 --> Class类 11 * 成员变量 --> Field类 12 * 构造方式 --> Constructor类 13 * 成员方式 --> Method类 14 * 15 * 获取class文件对象的方式: 16 * A:Object类的getClass()方式 17 * B:数据类型的静态属性class(任意数据类型都具备有三个 class静态属性) 18 * C:Class类中的静态方式(将类名作为字符串传递给Class类中的静态方式forName) 19 * public static Class forName(String className) 20 * 21 * 一般大伙到底使用谁呢? 22 * A:被委托人玩 任选一种 ,第二种比较方便 23 * B:开发时 第一种 24 * 为那先 呢?可能性第一种 是有三个 字符串,而就有有三个 具体的类名。没能 大伙就还可不还可以 把没能 的字符串配置到配置文件中。 25 */ 26 public class ReflectDemo { 27 public static void main(String[] args) throws ClassNotFoundException { 28 // 方式A 29 Person p = new Person(); 300 Class c = p.getClass(); 31 32 Person p2 = new Person(); 33 Class c2 = p2.getClass(); 34 35 System.out.println(p == p2); // false 36 System.out.println(c == c2); // true 37 38 // 方式B 39 Class c3 = Person.class; 40 // int.class; 41 // String.class; 42 System.out.println(c == c3); // true 43 44 // 方式C 45 // ClassNotFoundException 可不还可以 类的全路径(带包名的路径) 46 Class c4 = Class.forName("com.my.fanshe.Person"); 47 System.out.println(c == c4); // true 48 } 49 }

实例二:

package com.my.fanshe;

public interface JieKou {
    public void print();
}
package com.my.fanshe;

public class A implements JieKou {
    private String name;
    private int age;

    public A(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }


    @Override
    public void print() {

        System.out.println("实现A接口方式");
    }

    @Override
    public String toString() {
        return "A{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public int getAge() {
        return age;
    }
}
package com.my.fanshe;

public class B implements JieKou {

    @Override
    public void print() {
        System.out.println("实现B接口方式");
    }
}
package com.my.fanshe;

public class C {
    public void show(){
        System.out.println("实现C方式");
    }
}
package com.my.fanshe;

public class FansheDemo {
    public static void main(String[] args) throws Exception{
        //方式一:通过对象获得Class类类型(静态加载)
        A a = new A("张三",20);
        Class c = a.getClass();
        System.out.println("Class类类型为:"+c);
        //方式二:通过类名获得Class类类型
        Class c1 = B.class;
        System.out.println("Class类类型为:"+c1);
        //方式三:通过动态加载
        Class c2 = Class.forName("com.my.fanshe.C");
        System.out.println("Class类类型为:"+c2);
    }
}
运行结果:

Class类类型为:class com.my.fanshe.A
Class类类型为:class com.my.fanshe.B
Class类类型为:class com.my.fanshe.C

2、获取类的信息

package com.my.fanshe;

public interface JieKou {
    public void print();
}
package com.my.fanshe;

public class A implements JieKou {
    public String name;
    private int age;

    public A(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }


    @Override
    public void print() {

        System.out.println("实现A接口方式");
    }

    @Override
    public String toString() {
        return "A{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public int getAge() {
        return age;
    }

}
package com.my.fanshe;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class FansheDemo {
    public static void main(String[] args) throws Exception{
        //动态加载类,Class是表示当前类的类类型
        //获取字节码文件
        Class c = Class.forName("com.my.fanshe.A");
        // 通过Class类类型获得类的实例
        Constructor constructor = c.getConstructor(String.class,int.class);
        A a = (A)constructor.newInstance("张三",20);
        //获取公共属性的成员变量
        Field f = c.getField("name");
        System.out.println(f.get(a));
        //获取私有属性的成员变量
        Field f1 = c.getDeclaredField("age");
        System.out.println(f1.getType()+" "+f1.getName());
        //打开权限
        f1.setAccessible(true);
        System.out.println(f1.get(a));
        //获取方式并执行
        Method method = c.getMethod("getName");
        System.out.println(method.invoke(a));

        Method method1 = c.getMethod("getAge");
        System.out.println(method1.invoke(a));

        Method method2 = c.getMethod("print");
        method2.invoke(a);

        Method method3 = c.getMethod("toString");
        System.out.println(method3.invoke(a));




    }
}
运行结果:

张三
int age
20
张三
20
实现A接口方式
A{name='张三', age=20}

3、反射思维导图

1:反射(理解)
    (1)类的加载
        当多多系统进程


要使用某个类时,可能性该类还未被加载到内存中,则系统会通过加载连接初始化三步来实现对这俩类进行初始化。
        
        加载 
            而是指将class文件读入内存,并为之创建有三个


Class对象。
            任何类被使用时系统就有建立有三个


Class对象。
        连接
            验证:否是有正确的内部人员型态,并和而是类协调一致。
            准备:负责为类的静态成员分配内存,并设置默认初始化值。
            解析:将类的二进制数据中的符号引用替换为直接引用初始化 
            而是大伙以前讲过的初始化步骤。
        
        注意:Object类的方式:
                public final Class getClass()    返回对象的字节码文件对象
             Class类的方式:
                public String getName()    以 String 的形式返回此 Class 对象所表示的实体名称。(实体包括:类、接口、数组名、基本类型或 void)
                    即:还可不还可以

通过Class类中的有三个


方式,获取对象的真实类的全名称
    (2)类的初始化时机
        1.创建类的实例时。
        2.访问类的静态变量,可能性为静态变量赋值时。
        3.调用类的静态方式时。
        4.使用反射方式来强制创建某个类或接口对应的java.lang.Class对象时。
        5.初始化某个类的子类时。
        6.直接使用java.exe命令来运行某个主类时。

    (3)类加载器
        负责将.class文件加载到内存中,并为之生成对应的Class对象。
        着实大伙不可不还可以

关心类加载机制,而且了解这俩机制大伙就能更好的理解多多系统进程


的运行。
    (4)类加载器的组成
            Bootstrap ClassLoader     类加载器
            Extension ClassLoader     扩展类加载器
            Sysetm ClassLoader        系统类加载器
        
        Bootstrap ClassLoader     类加载器
            也被称为引导类加载器,负责Java核心类的加载。
            比如System类,String类等。在JDK中JRE的lib目录下rt.jar文件中(JDK8以前版本中的位置,JDK9/10位置变化了)。
            
        Extension ClassLoader     扩展类加载器
            负责JRE的扩展目录中jar包的加载。
            在JDK中JRE的lib目录下ext目录。
            
        Sysetm ClassLoader        系统类加载器
            负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径。
            一般大伙被委托人写的类通过系统类加载器来加载的。

猜你喜欢

1.5分pk10app赚钱 _【图文】林志颖想偷吃老婆月子餐 帽子深藏爱意成亮点

来源: 凤凰网 2015-12-11.5分pk10app赚钱 611:52:06   原文标题:【图文】林志颖想偷吃女

2020-06-02

分分飞艇app安卓_秋天凉了,多肉植物怎么养?

对于植物来说一年之计在于春而多肉之计则是春秋两季好不容易熬过了地狱般的夏季秋天又该为肉肉们做些那此呢?翻盆 秋天的工作非常多:翻盆、叶插、扦插、分分飞艇app安卓适当地调整肉肉

2020-06-02

10分时时彩安全吗_ 网络流行语:天生我笨必有用

【生活百科网】 首页生活小10分时时彩安全吗常识生活小窍门健康小常识健康饮食养生保健小偏方低碳生活运动健身急救常识热门搜索:健康常识问答一10分时时彩安全

2020-06-02

1分pk10技巧稳赚方法 _比达:母婴中高端市场持续增长 宝宝树孕育和亲宝宝月活用户领先

伴随1分pk10技巧稳赚方法 母1分pk10技巧稳赚方法 婴市场进入成熟期期期期图片 图片 的句子,中国母婴市场发展步入新阶段,其中电商领域发展放缓,中高端市场持续增长。比达

2020-06-02

分分飞艇手机版ios_ 春季喝点醋 轻松排毒素

冬季胡吃海喝,体内积累了不少毒素,春季草木生发,要排除体内淤积的毒素不妨喝或分分飞艇手机版ios多或少醋,在春天或多或少或多或少 都能否喝它,帮你排毒是一件非常非常轻松的事情

2020-06-02