反射


多态是不能调用子类独有的方法的,形象来说程序是不知道user是个child
如果能在运行过程中知道user是什么类型,那就能用child里面的方法了
好比通过照镜子知道自己长什么样,java中就有反射这种机制在运行中得到对象的类型等相关信息

通过反射的方式来获取整体的对象--类对象

Class<? extends User> aClass = user.getClass();//类对象


编译后的字节码文件
javap是java提供的反编译cmd命令

创建完类对象就能根据类对象获取一些信息了

package Reflect;

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

public class demo {
    public static void main(String[] args) throws Exception{
        User user = new Child();
        Class<? extends User> aClass = user.getClass();//类对象
        //java万物皆对象,Class对应编译后的字节码文件.class

        //获取类名
        System.out.println(aClass.getName());//Reflect.Child 包名.类名
        System.out.println(aClass.getSimpleName());//类名 Child
        System.out.println(aClass.getPackage());//类所在的包 package Reflect

        //获取类的父类
        System.out.println(aClass.getSuperclass());//class Reflect.User

        //获取类的接口
        Class<?>[] interfaces = aClass.getInterfaces();
        System.out.println(interfaces.length);//0 Child类没实现任何接口

        //获取类的属性
        //Field是属性对象
        Field f1 = aClass.getField("xxx");//根据传入的字符串如xxx来获取对应的属性,只能获取public
        Field f2 = aClass.getDeclaredField("xxxx");//获取属性名为xxxx的属性,不论权限(包括private)

        Field[] fields = aClass.getFields();//获取所有权限为public的属性
        Field[] declaredFields = aClass.getDeclaredFields();//获取所有属性(包括private)

        //获取类的方法
        //Method是方法对象
        Method m1 = aClass.getMethod("xx");//获取方法名为xx的方法,只能获取public修饰的方法
        Method m2 = aClass.getDeclaredMethod("xxx");//获取名为xxx的方法,不论权限

        Method[] methods = aClass.getMethods();//获取所有public修饰的方法
        Method[] declaredMethods = aClass.getDeclaredMethods();//获取所有方法

        //获取构造方法
        //Constructor是构造器对象
        Constructor<? extends User> constructor = aClass.getConstructor();
        Constructor<?>[] constructors = aClass.getConstructors();
        Constructor<? extends User> declaredConstructor = aClass.getDeclaredConstructor();
        Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();

        //获取权限(修饰符)
        int modifiers = aClass.getModifiers();//多个修饰符融合成了1个int值
        //Modifier提供方法来判断是否为xx修饰符,涉及位运算
        boolean aProtected = Modifier.isProtected(modifiers);//判断是否有protected修饰符
        System.out.println(modifiers);
        System.out.println(aProtected);

    }
}
class User {
    public void test1(){
        System.out.println("test1");
    }
}
class Child extends User{
    public void test2(){
        System.out.println("test2");
    }
}

用反射实现登录功能

package Reflect;

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

public class demo {
    public static void main(String[] args) throws Exception{
        //不直接创建对象,而是构造方法对象
        //先拿到类对象
        //有三种方式
        Class employeeClass = Employee.class;//拿到了Employee这个类的信息,等同于拿到了字节码文件
        /*
        还有以下两种方式
        Class<?> employeeClass = Class.forName("Reflect.Employee");//Class.forName("包名.类名")
        Class<? extends Employee> employeeClass = new Employee().getClass();
        */        

        //再拿到构造方法对象
        Constructor declaredConstructor = employeeClass.getDeclaredConstructor();
        /*Employee类没写构造器,JVM会默认提供一个声明的无参构造器*/
        //通过构造方法来构造实例
        Object emp = declaredConstructor.newInstance();//构建出了Employee的对象emp
        //实现登录验证需要获取属性
        Field fUsername = employeeClass.getField("username");
        Field fPassword = employeeClass.getField("password");
        //属性赋值
        fUsername.set(emp,"admin");//set赋值,(对象,值)
        fPassword.set(emp,"123456");
        //获取方法
        Method mLogin = employeeClass.getMethod("login");
        //调用方法
        Object result = mLogin.invoke(emp);//调用emp的login(mLogin对应的login)方法
        System.out.println(result);//true
    }
}
class Employee {
    public String username;
    public String password;

    public boolean login(){
        if("admin".equals(username) && "123456".equals(password)){
            return true;
        }else {
            return false;
        }
    }
}

反射最重要的用途就是开发各种通用框架。

类加载器

package Reflect;

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

public class demo {
    public static void main(String[] args) throws Exception{
        Class<User> userClass = User.class;//获取User类的信息
        ClassLoader classLoader = userClass.getClassLoader();//获取类的加载器对象
        System.out.println(classLoader);//sun.misc.Launcher$AppClassLoader@18b4aac2
        //核心类库 > 平台类库 > 自定义类
        //自定义类的上一级就是平台类
        System.out.println(classLoader.getParent());//sun.misc.Launcher$ExtClassLoader@1b6d3586
        //jdk9后会把extclassloader改为platformclassloader
    }
}
class User {}


String是核心类,获取它的加载器对象结果为null。因为启动类加载器采用操作系统平台语言实现

posted @ 2023-02-24 01:49  ben10044  阅读(13)  评论(0编辑  收藏  举报