java反射机制

本文详细介绍了Java反射机制的原理和应用,包括反射的用途、相关类和包,如何通过Class.forName获取Class实例,资源绑定器的使用,以及类加载器的工作原理和双亲委派机制。还展示了如何通过反射设置属性和调用对象方法。
摘要由CSDN通过智能技术生成

1. 反射机制

1.1、 反射机制有什么用?
通过java语言中的反射机制可以操作字节码文件。
优点类似于黑客。( 可以读和修改字节码文件。)
通过,反射机制可以操作代码片段。(class文件。 )
1.2、反射机制的相关类在哪个包下?
java. lang. reflect. *;
1.3、反射机制相关的重要的类有哪些?
java.lang.Class:代表整个字节码,代表一个类型
java.lang.reflect.Method:代表字节码中的方法字节码。,
java.lang.reflect.Constructor:代表字节码中的构造方法字节码
java.lang.reflect.Field:代表字节码中的属性字节码,代表类中的成员变量(静态变量)

java. langr.Class:
public class User {

// Field
int no;
// Constructor
public User() {
}
public User (int no) {
this.no = no;
}

// Method
public void setNo (int no) {
this.no = no;
}
public int getNo() {
return no;
}
}
package 反射;

/*
要操作一个类的字节码,需要首先获取到这个类的字节码,怎么获取java. lang. Class实例?
三种方式
第一种:Class c = Clasd.forName( "完整类名带包名");
第二种:Class c =对象. getClass();
第三种:Class c =任何类型.class;
*/

import java.util.Date;

public class 获取Class的三种方式 {
    public static void main(String[] args) {
        /*Class. forName()
        1、静态方法
        2、方法的参数是一个字符串。
        3、字符串需要的是一个完整类名。
        4、完整类名必须带有包名。java. lang包也不能省略。*/
        Class c1=null;
        Class c2=null;
        Class c3=null;
        Class c4=null;

        try {
            c1=Class.forName("java.lang.String");//c1代表String.class文件,或者说C1代表String类型
            c2=Class.forName("java.lang.Integer");//c2代表Integer类型
            c3=Class.forName("java.lang.System");
            c4=Class.forName("java.util.Date");
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        String s="abc";
        Class x=s.getClass();//x代表String.class字节码文件,代表String类型
        System.out.println(x==c1);//==判断的是对象的内存地址。true

        Date date=new Date();
        Class y=date.getClass();
        System.out.println(y==c4);//true(c2与y两个变量保存的内存地址都是一样的都指向方法区中的字节码文件)。

        //第三种方式, java语言中任何-种类型,包括基本数据类型,它都有. class属性。
        Class z = String.class; // z代表String类型
        Class k = Date.class; // k代表Date类型
        Class f = int.class; // f代表int类型
        Class e = double.class; // e代表double类型
        System.out.println(x == z); // true
        System.out.println(z);

    }
}

2.资源绑定器

import java.util.ResourceBundle;

/*  java.util包下提供了- -个资源绑定器,便于获取属性配置文件中的内容。
       使用以下这种方式的时候,属性配置文件xxx.properties必须放到类路径下。
       来*/
public class 资源绑定器 {
    public static void main(String[] args) {

        //资源绑定器,只能绑定xxx.properties文件,并且这个文件必须在类路径下。文件扩展名必须也是properties
        //并且在写路径的时候,路径后面的扩展名不能写
        ResourceBundle bundle=ResourceBundle.getBundle("classinfo2");
        String className=bundle.getString("className");
        System.out.println(className);
    }
}

3、关于JDK中自带的类加载器:

3.1、什么是类加载器?
专门负贲加载类的命令/工具。
ClassLoader

3.2、 JDK中自带了3个类加载器
启动类加载器:rt.jar
扩展类加载器:ext/*. jar
应用类加载器:classpath

3.3、假设有这样一段代码:
string s = “abc” ;
代码在开始执行之前,会将所需要类全部加载到JVM当中。
通过类加载器加载,看到以上代码类加载器会找String.class
文件,找到就加载,那么是怎么进行加载的呢?
首先通过"启动类加载器”加载。
注意:启动类加载器专门加载: C: \Program Files\Java\jdk1. 8
rt. jar中都是JDK最核心的类库。
如果通过"启动类加载器”加载不到的时候,
会通过"扩展类加载器”加载。
注意:扩展类加载器专门加载: c: \Program Files\Java\jdk1. 8
如果扩展类加载器"没有加载到,那么
会通过\应用类加载器"加载。
注意:应用类加载器专门加载:classpath中的类。

3.4、java中为了保证类加载的安全,使用了双亲委派机制。
优先从启动类加载器中加载,这个称为父"。
父"无法加载到,再从扩展类加载器中加载,
这个称为“母"。双亲委派。如果都加载不到,
才会考虑从应用类加载器中加载。直到加载
到为止。

3.5、通过反射机制给属性赋值。

//反射属性Field
public class Student {
    // Field翻译为字段,其实就是属性1成员
    // 4个Field,分别采用了不同的访问控制权限修饰符

    public int number;//Field对象
    private String name;
    protected int age;
    boolean sex;


}
public class 通过反射机制获取访问对象的属性 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        //使用反射机制,怎么访问一个对象的属性set get
        String Student = null;
        Class studentClass=Class.forName("reflect.Student");
        Object obj= studentClass.newInstance();//底层调用无参数构造方法

        //获取number属性(根据属性的名称来获取Field)
        Field numberFiled=studentClass.getDeclaredField("number");

        //给Obj(Student对象)的number属性赋值
        /*虽然使用了反射机制,但是三要素还是缺一不可:
        要素1 :obj对象
        要素2 :number属性
        要素3 :2222值
        注意:反射机制让代码复杂了,但是为了一个“灵活”,这也是值得的
         */
        numberFiled.set(obj,2222);//
        System.out.println(numberFiled.get(obj));

        //可以访问私有属性吗?不行
        Field nameField=studentClass.getDeclaredField("name");//先通过属性的名字拿到属性

         // 打破封装(反射机制的缺点:打破封装,可能会给不法分子留下机会! ! ! )
        //这样设置完之后,在外部也是可以访问private的。

        nameField.setAccessible(true);
        //给name属性赋值
        nameField.set(obj,"lisi");
        System.out.println(nameField.get(obj));



    }
}

3.6通过反射机制调用对象的方法

   /*反射机制,让代码很具有通用性,可变化的内容都是写到配置文件当中,
    将来修改配置文件之后,创建的对象不-样了,调用的方法也不同了,
    但是java代码不需要做任何改动。这就是反射机制的魅力。*/
public class UserService {
    /**
     * 登录方法
     * @param name  用户名
     * @param password  密码
     * @return true表示登录成功,false表示登录失败
     */
    public boolean login(String name,String password){
        if("admin".equals(name)&&"123".equals(password)){
            return true;
        }else{
            return false;
        }
    }
    public void  login(int i){

    }
    //系统退出方法
    public void logout(){
        System.out.println("系统已经安全退出");
    }
}

public class 通过反射机制调用对象的方法 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {

        //不使用反射机制,怎么调用方法
        //创建对象
        UserService userService=new UserService();
        //调用方法
        boolean loginSuccess=userService.login("admin","123");
        System.out.println(loginSuccess?"登录成功":"登录失败");


        //使用反射机制来调用一个对象的方法
        Class userServiceClass=Class.forName("reflect.UserService");
        //创建对象
        Object obj=userServiceClass.newInstance();
        //获取method
        Method loginMethod= userServiceClass.getDeclaredMethod("login", String.class, String.class);
       // Method loginMethod1= userServiceClass.getDeclaredMethod("login", int.class);

        //调用方法
        //调用方法有几个要素?也需要4要素。
        //反射机制中最最最最最重要的一个方法,必须记住。
        /*四要素:
        loginMethod方法
        obj对象
        "admin", "123” 实参
        retValue返回值
        */
        Object retValue=loginMethod.invoke(obj,"admin","123");
        System.out.println(retValue);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值