java反射基础

什么是反射

本文为初学java者反射基础

在运行状态中,对于任意一个类都能够知道这个类所有属性和方法,并且对任意一个对象,都能够调用它的任意一个方法;这种动态获取信息以及动态调用对象方法的功能成为Java语言的反射机制
Person p = new Student()
Person是编译时类型 Student是运行时类型
编译时我没有办法预知对象和类属于哪个类型,而需要在运行时获取类或对象信息就需要使用反射.

一些基础理解
根据类型名称字符串,生成相应对象
类的执行过程
编译(.java生成.class文件)-----加载(把.class的二进制字节码文件加载到内存(栈堆方法区)中)—连接
连接包含三个(验证(验证.class文件格式是否规范,语义是否正确)—准备(准备阶段给类变量,static分配内存,并且设置这些类变量static 初始值的阶段,给类变量赋的是系统原值)----解析(把一个符号引用转换为一个直接引用,并且分配地址过程)----初始化(在初始化类的 里面会去检查有没有继承关系,先看父类有无初始化,没有先初始父类,然后再初始自己。会把用户给static赋的值覆盖掉原值,如果有 代码块会执行一遍)被Java程序首次主动使用才会用初始化 new
将A.class存进方法区运行时内存区—为A.class生成一个唯一的class对象—把这个class对象放到堆里
JVM将A.class文件读入内存方法区
JVM为A.class创建唯一的Class对象
有Class对象就可以访问方法区里对应的数据
通过Class类对象反向的读取它对应的类里的信息(属性 方法)反向生成Class对象生成类的实例
Goods goods = (Goods类名包名)Class.forName(className完整类名Person).newInstance();–新的实例(转化为你想要的类型)
传类名获取相应类名对象
测试地方写包名,包名点类名Goods goods = factory.getGoods(“cn.com.ref.after.Foods”)

反射场景应用

反射优点
运行期间类型的判断,动态类加载
提高了程序的灵活性,扩展性,降低耦合性
提高了自适应能力,无需提前硬编码目标类
反射缺点
性能问题
安全限制
内部暴露
框架 安装插件功能都需要反射

反射的使用

//通过getClass()方法 获取Class对象

我们先创建一个User类,放属性

public class User implements Userss{
    static {
        System.out.println("静态代码块");
    }
    private String username;
    private int userage;

    public User(){}

    public User(String username, int userage) {
        this.username = username;
        this.userage = userage;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public int getUserage() {
        return userage;
    }

    public void setUserage(int userage) {
        this.userage = userage;
    }
}
public interface Userss {//这里放一个接口,方便后面的测试使用
}
public class GetClass1 {
    public static void main(String[] args) {
        //通过getClass()方法 获取Class对象
        User user=new User();//静态代码块是它运行的,跟下面没关系
        Class<? extends User> aClass = user.getClass();//Object中的方法(加不加泛型没有问题) 上届通配符 将父类作为上届可以传递父类或者父类的子类
        System.out.println(aClass);

        Class<? extends User> aClass2 = user.getClass();
        System.out.println(aClass==aClass2);//结果为true 因为获取的是同一个对象
    }

}

输出结果

静态代码块
class api.fanshe.shangke.User
true

//通过类名.class 获取到Class对象(静态代码块没出来说明运行时没加载类 对象都没创建)

public class GetClass2 {
    //通过类名.class 获取到Class对象(静态代码块没出来说明运行时没加载类 对象都没创建)
    public static void main(String[] args) {
        Class<User> userClass = User.class;
        Class<User> userClass2 = User.class;
        System.out.println(userClass);
        System.out.println(userClass==userClass2);//true
    }
}

输出结果

class api.fanshe.shangke.User
true

//通过Class的 Class.forName(“全类名”)

public class GetClass3 {
    //通过Class的 Class.forName("全类名demo10反射.getClassDemo.Use")
//会加载目标类  (静态代码块出来了)
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> aClass = Class.forName("api.fanshe.shangke.User");
        Class<?> aClass2 = Class.forName("api.fanshe.shangke.User");
        System.out.println(aClass);
        System.out.println(aClass==aClass2);//true

        // Class.forName("com.mysql.cj.jdbc.Driver");


    }
}

输出结果

静态代码块
class api.fanshe.shangke.User
true

一些基础方法(还有很多不一一列举)

public class GetClassInfo {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> aClass = Class.forName("api.fanshe.shangke.User");
        //直接打印aclass
        System.out.println(aClass);
        //获取类名(全类名)
        String name = aClass.getName();
        System.out.println(name);
        //获取包名
        Package aPackage = aClass.getPackage();
        System.out.println(aPackage);
        //获取父类
        Class<?> superclass = aClass.getSuperclass();
        System.out.println(superclass);//父类为Object类
        //获取这个类实现的接口 得到一个数组
        Class<?>[] interfaces = aClass.getInterfaces();
        System.out.println(Arrays.toString(interfaces));

    }
}

输出结果

静态代码块
class api.fanshe.shangke.User
api.fanshe.shangke.User
package api.fanshe.shangke
class java.lang.Object
[interface api.fanshe.shangke.Userss]

Process finished with exit code 0

获取构造
再来一个User类,稍微改动

public class User {
    static {
        System.out.println("静态代码块");
    }

    private String username;
    private int userage;

    public User() {
    }

    private User(int userage) {
        this.userage = userage;
    }

    public User(String username) {
        this.username = username;
    }

    public User(String username, int userage) {
        this.username = username;
        this.userage = userage;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public int getUserage() {
        return userage;
    }

    public void setUserage(int userage) {
        this.userage = userage;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", userage=" + userage +
                '}';
    }
}

public class GetConstructor1 {//获取构造
    public static void main(String[] args) throws NoSuchMethodException {
        //获取所有构造方法数组 任何访问修饰符的构造 都可以拿到
        //私有构造也能拿到
        Class<User> userClass = User.class;
        Constructor<?> []carr1 = userClass.getDeclaredConstructors();
       // System.out.println(Arrays.toString(carr1));
        for(Constructor<?> constructor:carr1){
            System.out.println(constructor);
        }
        System.out.println("=========");
        //获取所有Public修饰的构造
        Constructor<?>[] carr2 = userClass.getConstructors();
        for(Constructor<?> constructor:carr2){
            System.out.println(constructor);
        }

        System.out.println("=========");
        //获取带参数构造方法     凡是带Declared就是全部获取
        Constructor<User> declaredConstructor = userClass.getDeclaredConstructor(String.class, int.class);
        System.out.println(declaredConstructor);
        Constructor<User> declaredConstructor1 = userClass.getDeclaredConstructor(int.class);
        System.out.println(declaredConstructor1);
        System.out.println("================");
        //获取带参数的构造方法 不带Declared就是获取非私有的
        Constructor<User> constructor = userClass.getConstructor(String.class);
        System.out.println(constructor);
        //私有的 没法用getConstructor去调用
       /* Constructor<User> constructor1 = userClass.getConstructor(int.class);
        System.out.println(constructor1);*///报错
    }

}

输出结果

public api.fanshe.shangke2.User(java.lang.String,int)
public api.fanshe.shangke2.User(java.lang.String)
private api.fanshe.shangke2.User(int)
public api.fanshe.shangke2.User()
=========
public api.fanshe.shangke2.User(java.lang.String,int)
public api.fanshe.shangke2.User(java.lang.String)
public api.fanshe.shangke2.User()
=========
public api.fanshe.shangke2.User(java.lang.String,int)
private api.fanshe.shangke2.User(int)
================
public api.fanshe.shangke2.User(java.lang.String)

Process finished with exit code 0

Constructor类的使用

public class GetConstructor2 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //Constructor类的使用
        Class<User> userClass = User.class;
        Constructor<User> constructor = userClass.getConstructor(String.class, int.class);
        //通过Constructor的newInstance方法 创建对象
        User aaaa = constructor.newInstance("aaaa", 32);
        System.out.println(aaaa);
    }
}

输出结果

静态代码块
User{username='aaaa', userage=32}

Process finished with exit code 0

获取属性
还是一个User类,不做修改

public class GetFields1 {
    //获取所有属性 包括私有
    public static void main(String[] args) throws NoSuchFieldException {
        Class<User> userClass = User.class;
        Field[] declaredFields = userClass.getDeclaredFields();
        for (Field field:declaredFields){
            System.out.println(field);
            //获取属性的具体信息
            Class<?> type = field.getType();
            System.out.println(type);
            String name = field.getName();
            System.out.println(name);
        }
        System.out.println("===============");
        //不包括私有
        Field[] fields = userClass.getFields();
        for (Field field1:fields){
            System.out.println(field1);
            //获取属性的具体信息
            Class<?> type = field1.getType();//type这个属性具体什么类型
            System.out.println(type);
            String name = field1.getName();
            System.out.println(name);
        }
        System.out.println("=================");
        //获取公有
        Field userage = userClass.getField("userage");
        System.out.println(userage);
        //获取私有
        Field declaredField = userClass.getDeclaredField("username");
        System.out.println(declaredField);
    }
}

输出结果

private java.lang.String api.fanshe.shangke3.User.username
class java.lang.String
username
public int api.fanshe.shangke3.User.userage
int
userage
===============
public int api.fanshe.shangke3.User.userage
int
userage
=================
public int api.fanshe.shangke3.User.userage
private java.lang.String api.fanshe.shangke3.User.username

Process finished with exit code 0

利用Class 与Field 配合创建对象

public class GetFields2 {
    //利用Class 与Field 配合创建对象
    public static void main(String[] args) throws NoSuchFieldException, InstantiationException, IllegalAccessException {
        Class<User> userClass = User.class;
        Field userage = userClass.getField("userage");
        //通过Class的 newInstance方法 实例化对象
        User user = userClass.newInstance();
        System.out.println(user);
        //拿到的field属性
        userage.set(user,99);
        System.out.println(user);
        //私有的属性 构造方法 私有 能不能通过反射 创建对象
        Field username = userClass.getDeclaredField("username");
        System.out.println(username);
        //私有 需要获取权限 通过setAccessible(true) 增加权限
        username.setAccessible(true);
        username.set(user,"aaa");
        System.out.println(user);

    }
}

输出结果

User{username='null', userage=0}
User{username='null', userage=99}
private java.lang.String api.fanshe.shangke3.User.username
User{username='aaa', userage=99}

Process finished with exit code 0

通过Class的 newInstance方法 实例化对象

public class GetFields3 {
    public static void main(String[] args) throws NoSuchFieldException, InstantiationException, IllegalAccessException {
        Class<User> userClass = User.class;
        Field userage = userClass.getField("userage");
        //通过Class的 newInstance方法 实例化对象
        User user = userClass.newInstance();
        userage.set(user,99);
        System.out.println(user);
        Field username = userClass.getDeclaredField("username");
        username.setAccessible(true);
        //私有 需要获取权限 通过setAccessible(true) 增加权限
        username.set(user,"aaa");
        System.out.println(user);
    }
}

输出结果

User{username='null', userage=99}
User{username='aaa', userage=99}

Process finished with exit code 0

获取所有本类方法
先创建User实现类,还有一个user11的接口

public class User implements User11{
    private String username;
    private int userage;

    public User() {
    }

    public User(String username, int userage) {
        this.username = username;
        this.userage = userage;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {

        this.username = username;
    }

    public int getUserage() {
        return userage;
    }

    public void setUserage(int userage) {
        this.userage = userage;
    }

    public void funPublic(){
        System.out.println("共有方法");
    }
    private void funPrivate(){
        System.out.println("私有方法");
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", userage=" + userage +
                '}';
    }


    @Override
    public void ttt() {

    }

    @Override
    public void ffff() {
        User11.super.ffff();
    }
}
public interface User11 {
    void ttt();

    default void ffff(){

    }
}
public class GetMethods1 {
    public static void main(String[] args) throws NoSuchMethodException {
        //获取所有本类方法
        Class<User> userClass = User.class;
        Method[] declaredMethods = userClass.getDeclaredMethods();
        for (Method declaredMethod:declaredMethods){
            System.out.println(declaredMethod);
        }
        System.out.println("=================");
        //获取的本类 以及父类 以及父接口 所有的公共方法
        Method[] methods = userClass.getMethods();
        for (Method method:methods){
            System.out.println(method);//因为Object为顶级父类 所以它的一些方法也会获取
            System.out.println(method.getName());

        }//接口里的变量都是静态常量
        System.out.println("============");
        Method funPrivate = userClass.getDeclaredMethod("funPrivate");
        Method funPublic = userClass.getMethod("funPublic");
        Method setUsername = userClass.getMethod("setUsername", String.class);


    }
}

输出结果

public java.lang.String api.fanshe.shangke4.User.toString()
public void api.fanshe.shangke4.User.ttt()
public void api.fanshe.shangke4.User.ffff()
public void api.fanshe.shangke4.User.setUsername(java.lang.String)
private void api.fanshe.shangke4.User.funPrivate()
public java.lang.String api.fanshe.shangke4.User.getUsername()
public int api.fanshe.shangke4.User.getUserage()
public void api.fanshe.shangke4.User.funPublic()
public void api.fanshe.shangke4.User.setUserage(int)
=================
public java.lang.String api.fanshe.shangke4.User.toString()
toString
public void api.fanshe.shangke4.User.ttt()
ttt
public void api.fanshe.shangke4.User.ffff()
ffff
public void api.fanshe.shangke4.User.setUsername(java.lang.String)
setUsername
public java.lang.String api.fanshe.shangke4.User.getUsername()
getUsername
public int api.fanshe.shangke4.User.getUserage()
getUserage
public void api.fanshe.shangke4.User.funPublic()
funPublic
public void api.fanshe.shangke4.User.setUserage(int)
setUserage
public final void java.lang.Object.wait() throws java.lang.InterruptedException
wait
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
wait
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
wait
public boolean java.lang.Object.equals(java.lang.Object)
equals
public native int java.lang.Object.hashCode()
hashCode
public final native java.lang.Class java.lang.Object.getClass()
getClass
public final native void java.lang.Object.notify()
notify
public final native void java.lang.Object.notifyAll()
notifyAll
============

Process finished with exit code 0

invoke

public class GetMethods2 {
    public static void main(String[] args) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        //invoke给谁设置,设置什么值,通过反射调用方法
        Class<User> userClass = User.class;
        Method method = userClass.getMethod("setUsername", String.class);
        //获取对象实例
        User user = userClass.newInstance();
        //通过反射 调用对象方法
        method.invoke(user,"ccc");
        System.out.println(user);

        Method funPublic = userClass.getMethod("funPublic");
        funPublic.invoke(user);

        Method funPrivate = userClass.getDeclaredMethod("funPrivate");
        funPrivate.setAccessible(true);//不加这个直接invoke会报错
        funPrivate.invoke(user);
    }
}

输出结果

User{username='ccc', userage=0}
共有方法
私有方法

Process finished with exit code 0

setAccessible() 方法


public class AccessDemo {
    //setAccessible() 方法
    /*
    1.私有临时关闭访问权限 让反射可以进行
    2.是启用和禁用安全访问检查开关
    默认值为false
    为true时 指反射的对象在使用时应该取消安全访问检查 耗时降低
    为false时 指反射的对象在使用时需要实施安全访问检查
     */
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method getName = A.class.getDeclaredMethod("getName");
//默认为false 检查开启的 需要实施安全检查
        System.out.println(getName.isAccessible());
        A a=new A();
        a.setName("vvv");
        long l1 = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            getName.invoke(a);
        }
        System.out.println("正常为检查状态 耗时为:"+(System.currentTimeMillis()-l1));
        //此时我关闭掉安全检查
        getName.setAccessible(true); //关闭
        long l2 = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            getName.invoke(a);
        }
        System.out.println("关闭检查状态 setAccessible(true) 耗时为:"+(System.currentTimeMillis()-l2));

    }
}
class A{
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

输出结果

false
正常为检查状态 耗时为:2733
关闭检查状态 setAccessible(true) 耗时为:1885

Process finished with exit code 0

反射访问私有

public class Demo {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//        User user = new User();
//        User user = new User("???");
//        无法创建User对象 因为构造方法 私有 又没有无参构造

        Class<User> userClass = User.class;
        //私有构造获取
        Constructor<User> declaredConstructor = userClass.getDeclaredConstructor(String.class);
        //临时取消访问权限
        declaredConstructor.setAccessible(true);
        User user = declaredConstructor.newInstance("一个名字");
        user.fun();
    }
}
//反射可以创建私有内容 那么反射安全么???
class User{
    private User(String name){
        System.out.println("name为:"+name);
        System.out.println("私有构造方法");
    }
    public void fun(){
        System.out.println("成员方法");
    }
}

输出结果

name为:一个名字
私有构造方法
成员方法

Process finished with exit code 0

反射耗时

public class TimeUseing {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        Class<?> aClass = Class.forName("api.fanshe.shangke5.User1");
        User1 user1=(User1) aClass.newInstance();
        long lr = System.currentTimeMillis();
        Method setUsername = aClass.getMethod("setUsername", String.class);
        for (int i = 0; i < 1000000000; i++) {
            setUsername.invoke(user1,"aaa");
        }
        //反射耗时
        System.out.println("反射耗时");
        System.out.println(System.currentTimeMillis()-lr);
        long lf = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            user1.setUsername("bbb");
        }
        //非反射耗时
        System.out.println("非反射耗时");
        System.out.println(System.currentTimeMillis()-lf);
    }
}
//反射可以创建私有内容 那么反射安全么???
//反射耗时大 为什么还需要反射
class User1{
    static {
        System.out.println("静态代码块");
    }
    private String username;
    private int userage;

    public User1() {
    }

    public User1(String username, int userage) {
        this.username = username;
        this.userage = userage;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public int getUserage() {
        return userage;
    }

    public void setUserage(int userage) {
        this.userage = userage;
    }
}

输出结果

静态代码块
反射耗时
3148
非反射耗时
56

Process finished with exit code 0

控制顺序

public class SunX {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
        Demo01 demo01=new Demo01();
        if(args!=null &&args.length>0){
            Class<? extends Demo01> aClass = demo01.getClass();
            Method[] methods = aClass.getMethods();

            for (String arg : args) {
                for (int i = 0; i < methods.length; i++) {
                    if(arg.equalsIgnoreCase(methods[i].getName())){
                        methods[i].invoke(demo01);
                    }
                }
            }
        }else {
            demo01.m1();
            demo01.m2();
            demo01.m3();
        }


    }
}
class Demo01 {
    public void m1(){
        System.out.println("111111111111");
    }
    public void m2(){
        System.out.println("2222222222222");
    }
    public void m3(){
        System.out.println("3333333333333333");
    }
}
正常输出结果为
111111111111
2222222222222
3333333333333333

Process finished with exit code 0

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
通过这几步可以改变输出顺序

还有思考我在代码中提出的问题?
//反射可以创建私有内容 那么反射安全么???
//反射耗时大 为什么还需要反射

下一节注解

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值