java 反射--Java笔记

本文详细介绍了Java反射机制,包括反射的作用、相关类的使用,以及类加载的三个阶段:加载、连接和初始化。通过反射,可以在运行时动态地获取类的内部信息并操作对象。同时,文章探讨了反射的优缺点,以及如何通过setAccessible()方法实现访问权限的控制。
摘要由CSDN通过智能技术生成

目录

一.反射

1.机制

2.反射机制可以完成:

3.与反射相关的类

4.反射的优点和缺点

二.类加载

1.类加载的三个阶段

①.加载(Loading)

②.连接(Linking)

③.初始化(initialization)

三.反射相关的类与方法

1.Class类

Ⅰ.获取 Class 类对象

Ⅱ.那些类型有 Class 对象

Ⅲ.Class 类的方法

2..Field的方法

3.Method的方法

4.Constructor的方法

5.爆破:setAccessible


一.反射

1.机制

①.在不修改源码的情况下来控制程序

②.在反射中可以把方法视为对象

③.反射允许程序在执行时借助 Reflection API 来取得任意类的内部信息(变量、方法、构造器等),并能操作对象的属性及方法

④.加载完类之后,会产生一个 Class 类型的对象(一个类只有一个),这个对象包含了类的完整结构信息,通过这个对象得到类的结构,称之为反射

2.反射机制可以完成:

①.在运行时判断任意一个对象所属的类

②.在运行时构造任意一个类的对象

③.在运行时得到和调用任意一个类所具有的变量和方法

④.生成动态代理

3.与反射相关的类

①.Class:Class对象表示某个类加载后的对象

②.Method:代表类的方法

③.Field:代表类的变量

④.Constructor:代表类的构造方法

⑤.Method、Field、Constructor对象都有setAccessible()方法,作用是启动和禁止访问安全检查的开关,参数为 true,使用时可以提高反射的效率

4.反射的优点和缺点

①优点:可以动态的创建和使用对象,使用灵活

②.缺点:对执行速度有影响

二.类加载

①静态加载:编译时加载相关的类,如果没有这个类则报错

②.动态加载:运行时加载需要的类,没有这个类在运行时不使用此类不报错

③.类的加载时机:当创建对象时、当子类被加载时、调用类中的静态成员时、通过反射

1.类加载的三个阶段

①.加载(Loading)

JVM 在该阶段把字节码从不同的数据源(类的class 文件、jar包等)转化为二进制字节流在家到内存,并创建一个 Class 对象,

②.连接(Linking)

将类的二进制数据合并到 JRE 中

Ⅰ.验证(verification)

目的是确保 Class 文件的字节流中包含的信息符合当前 虚拟机的要求和不会危害虚拟机自身的安全

包括:文件格式验证(是否以 Oxcafe babe开头)、元数据验证、字节码验证 和 符号引用验证等

可以考虑使用 Xverify:none 参数来关闭部分验证措施,来缩短虚拟机类加载时间

Ⅱ.准备(Preparation)

JVM 会在该阶段对静态变量分配内存并初始化(数据类型对应的默认初始值如:0、null),这些变量所使用的内存都将在方法区中进行分配

Ⅲ.解析(Resolution)

虚拟机将常量池中的符号引用代换为直接引用的过程

③.初始化(initialization)

JVM 负责对类进行初始化(主要指静态成员),此阶段是执行 <clinit>()方法的过程,<clinit>()方法是由编译器 按语句在源文件中出现的顺序,依次收集类中的所有静态变量的 赋值和静态代码块中的语句。虚拟机会保证一个类的<clinit>()方法在多线程中被正确的 加锁和同步,如果多线程同时初始化一个类,那么只会有一个线程去执行这个类的<clinit>()方法,其他线程都需要等待阻塞。

三.反射相关的类与方法

1.Class类

①.Class 也是类,继承object,Class类不是 new 出来的,而是系统创建的

②.类只加载一次,所有一个类的Class 对象在内存中只有一个

③.每一个类的实例都会记得自己是哪个 Class 实例生成的

④.通过Class 对象可以完整的得到一个类的完整结构

⑤.Class对象是存放在堆中的,类的字节码二进制数据是放在方法区的,

Ⅰ.获取 Class 类对象

已知一个类的全类名,且该类在类路径下,可通过Class 类的静态方法 forName()来获取

已知具体的类,通过类的 class 来获取,该方式最安全

已知一个类的实例,调用该实例的 getClass()方法来获取Class 对象

getClassLoader()

Ⅱ.那些类型有 Class 对象

外部类、内部类、接口、数组、枚举、注解、基本数据类型和void

Ⅲ.Class 类的方法

1.forName()获取类的Class对象
2.getClass()查看类运行类型
3.getPackage()返回该类的包
4.newInstance()通过反射创建对象
5.getName()返回 Class 对象的实体名称
6.getSuperClass()返回当前Class对象的父类的Class对象
7.getInterfaces()获取当前Class对象的接口
8.getClassLoader()返回该类的类加载器
9.getSimpleName()获取简单类名
10.getFields()获取该类和父类 所有public 修饰的属性
11.getDeclaredFields()获取该类所有的属性
12.getMethods()获取该类和父类所有public 修饰的方法
13.getDeclaredMethods()获取该类所有的方法
14.getConstructors()获取本类所有的public修饰的构造器
15.getDeclaredConstructors()获取该类所有的构造器
16.getAnnotations()返回注解信息

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

public class App {
    public static void main(String[] args)
            throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException,
            SecurityException {

        // 1.forName()获取类的Class对象
        Class c = Class.forName("B");
        System.out.println("1.:  " + c);

        // 2.getClass()查看类运行类型
        System.out.println("2.:  " + c.getClass());

        // 3.getPackage()
        System.out.println("3.:  " + c.getPackage());

        // 4.newInstance
        Object o = c.newInstance();
        System.out.println("4.:  " + o.getClass());

        // 5.getName()返回 Class 对象的实体名称
        System.out.println("5.:  " + c.getName());

        // 6.getSuperClass()返回当前Class对象的父类的Class对象
        System.out.println("6.:  " + c.getSuperclass());

        // 7.getInterfaces()获取当前Class对象的接口
        System.out.println("7.:  " + c.getInterfaces());

        // 8.getClassLoader()返回该类的类加载器
        System.out.println("8.:  " + c.getClassLoader());

        // 9.getSimpleName()获取简单类名
        System.out.println("9.:  " + c.getSimpleName());

        // 10.getFields()获取该类和父类 所有public 修饰的属性
        Field[] f = c.getFields();
        System.out.println("10.:  ");
        for (Field field : f) {
            System.out.println(field);
        }

        // 11.getDeclaredFields()获取该类所有的属性
        f = c.getDeclaredFields();

        for (Field field : f) {
            System.out.println(field);
        }

        // 12.getMethods()获取该类和父类所有public 修饰的方法
        Method[] m = c.getMethods();
        System.out.println("12.:  ");
        for (Method method : m) {
            System.out.println(method);
        }

        // 13.getDeclaredMethods()获取该类所有的方法
        m = c.getDeclaredMethods();
        System.out.println("13.:  ");
        for (Method method : m) {
            System.out.println(method);
        }

        // 14.getConstructors()获取本类所有的public修饰的构造器
        Constructor[] cc = c.getConstructors();
        System.out.println("14.:  ");
        for (Constructor constructor : cc) {
            System.out.println(constructor);
        }

        // 15.getDeclaredConstructors()获取该类所有的构造器
        cc = c.getDeclaredConstructors();
        System.out.println("15.:  ");
        for (Constructor constructor : cc) {
            System.out.println(constructor);
        }

        // 16.getAnnotations()返回注解信息
        Annotation[] aa = c.getAnnotations();
        System.out.println("16.:  ");
        for (Annotation annotation : aa) {
            System.out.println(annotation);
        }

    }
}

interface AA {
}

class A {
    public void AA() {
    }

    void AAA() {
    }

    public A() {
    }

    A(int i) {
    }
}

@Deprecated
class B extends A implements AA {
    public String s;
    int i;

    public void bb() {
    }

    void bbb() {
    }

    public B() {
    }

    B(int i) {
    }
}

输出: 

1.:  class B
2.:  class java.lang.Class
3.:  null
4.:  class B
5.:  B
6.:  class A
7.:  [Ljava.lang.Class;@70dea4e
8.:  sun.misc.Launcher$AppClassLoader@6d06d69c
9.:  B
10.:  
public java.lang.String B.s
11.:  
public java.lang.String B.s
int B.i
12.:
public void B.bb()
public void A.AA()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) 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()
13.:
public void B.bb()
void B.bbb()
14.:
public B()
15.:
B(int)
public B()
16.:
@java.lang.Deprecated()

2..Field的方法

1.set()通过字段对象修改值
2.get()获得值

3.getModifiers()返回修饰符

0 为默认、1 = public、2 = private、

4 = protected、8 = static、16 = final

4.getType()返回类型
5.getName()返回属性名

        Class c = Class.forName("B");
        Object o = c.newInstance();
        Field f = c.getField("s");

        // 1.set()通过字段对象修改值
        f.set(o, "100");

        // 2.get()获得值
        System.out.println(f.get(o));

        // 3.getModifiers()返回修饰符 0 为默认、1 = public、2 = private、4 = protected、8 =
        // static、16 = final
        System.out.println(f.getModifiers());

        // 4.getType()返回类型
        System.out.println(f.getType());

        // 5.getName()返回属性名
        System.out.println(f.getName());

    }
}

@Deprecated
class B {
    public String s;
    int i;

    public void bb() {
    }

    void bbb() {
    }

    public B() {
    }

    B(int i) {
    }
}

输出:

3.Method的方法

方法与Field类似

 getParameterTypes()返回参数类型数组

 
        Class c = Class.forName("B");
        Object o = c.newInstance();
        Method[] m = c.getDeclaredMethods();
        System.out.println(m);
        for (Method method : m) {
            Class<?>[] cc = method.getParameterTypes();
            System.out.println(method);
            for (Class<?> class1 : cc) {
                System.out.println(class1);
            }
        }
class B {
    public String s;
    int i;

    public void bb(int i, String s, int ii) {
    }

    void bbb() {
    }

    public B() {
    }

    B(int i) {
    }
}

输出: 

4.Constructor的方法

和method类似

5.爆破:setAccessible

可以获取 private 修饰的构造器,静态属性 和 方法 参数可以写成 null

        Class c = Class.forName("B");
        Constructor cc = c.getDeclaredConstructor(int.class);//获取私有构造器
        cc.setAccessible(true);//爆破
        // 1构造器
        Object o1 = cc.newInstance(100);//创建实例
        System.out.println(o1);
        // 2构造器
        B b = (B) cc.newInstance(200);//创建实例
        System.out.println(b);
        //属性
        Field f = c.getDeclaredField("i");//获取私有属性 
        f.setAccessible(true);//爆破
        f.set(o1, 1);//修改值
        System.out.println(f.get(o1));输出属性值

        Method m = c.getDeclaredMethod("bb", String.class);//获取私有方法
        m.setAccessible(true);//爆破
        m.invoke(o1, "张三");//调用方法

class B {
    public String s;
    private int i;

    private void bb(String s) {
        System.out.println("bb()" + s);
    }

    public void bbb() {
    }

    public B() {
    }

    private B(int i) {
        this.i = i;
        System.out.println("B(int i)");
    }

    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return i + "";
    }
}

输出:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值