Java反射(java 基础、构造方法、变量、方法、mian方法、去泛型)

Java反射

参考别人的一句话,反射是框架设计的灵魂。

什么是反射?
在运行的状态中,对于任意一个类,都可以知道他的属性和方法,对于任意一个对象都能够调用他的方法和属性,这种动态获取信息以及动态调用对象的方法的功能成为java的反射机制。
首先获取该类的字节码文件对象。而解剖使用的是Class类中的方法,所以要先获取到每一个字节码文件对应的Class对象。
通过类的字节码文件得到Class对象,再利用Class中的方法将类中的各个组成部分:属性、方法、构造方法映射为一个个对象。
Class没有公共的构造方法,Class对象是在加载类的过程中JVM通过调用类加载器中的defineClass方法自动构造的。不需要自己创建

反射的应用
获取Class对象的三种办法:
①通过类对象的getClass()方法
②任何数据类型都拥有的一个静态的class属性
③通过Class类的静态方法Class.forName(String className)
使用①方法是因为Java中的类都是Object的父类,这个方法来自Object。
使用③方法创建Class对象,传参className是该类的全限定名。

/**
 * 反射复习1
 * 通过三种方式获取Class对象
 */
public class Reflect1 {

    /**
     * 使用 类.class对象获取反射对象
     * 输出 class com.entity.User
     */
    @Test
    public void testClass1(){
        System.out.println(User.class);
    }

    /**
     * 使用对象的getClass()方法获取反射对象
     * 输出:class com.entity.User
     */
    @Test
    public void testClass2(){
        User user=new User();
        System.out.println(user.getClass());
    }
    /**
     * 使用Class.forName获取反射对象
     * 输出:class com.entity.User
     */
    @Test
    public void testClass3(){
        try {
            Class<?> aClass = Class.forName("com.entity.User");
            System.out.println(aClass);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

从上面可以看出来,一个类只要一个Class对象。创建Class对象一般使用第三种方式。

获取构造方法

public class reflectConstructor {
    /**
     * 反射复习2
     * 反射获取对象的构造方法并使用
     */
    Class aClass;

    /**
     * 获取无参构造器
     * @throws Exception
     * 运行结果:无参构造器!
     */
    @Test
    public void getConstructorNoParam() throws Exception {
        aClass=Class.forName("com.entity.User");//会有找不到类的异常
        Constructor constructor = aClass.getConstructor();
        User user = (User) constructor.newInstance();
    }

    /**
     * 获取公有的有参构造方法
     * @throws Exception
     * 运行结果:有参构造器 age=2
     */
    @Test
    public void getConstructorHasParam() throws Exception {
        aClass=Class.forName("com.entity.User");
        Constructor constructor = aClass.getConstructor(Integer.class);
        User user= (User) constructor.newInstance(2);
    }

    /**
     * 获取受保护的有参构造方法
     * 要使用setAccessible(true)方法忽略修饰符的检查
     * @throws Exception
     * 输出:
     * protected com.entity.User(char)
     * 受保护的构造器 chr=a
     */
    @Test
    public void getConstructorProtect() throws Exception{
        aClass=Class.forName("com.entity.User");
        Constructor constructor=aClass.getDeclaredConstructor(char.class);
        System.out.println(constructor);
        constructor.setAccessible(true);
        User user= (User) constructor.newInstance('a');
    }

    /**
     * 获取私有的有参构造方法和受保护的一样,要忽略修饰符的检查
     * @throws Exception
     * 输出:
     * private com.entity.User(java.lang.String)
     * 私有构造器 username=1211
     */
    @Test
    public void getConstructorPrivate() throws Exception{
        aClass=Class.forName("com.entity.User");
        Constructor constructor=aClass.getDeclaredConstructor(String.class);
        System.out.println(constructor);
        constructor.setAccessible(true);
        User user= (User) constructor.newInstance("1211");
    }

    /**
     * 获取所有的公有的无参构造器
     * @throws Exception
     * 输出:
     * public com.entity.User(java.lang.Integer)
     * public com.entity.User()
     */
    @Test
    public void getAllContructorsPublic() throws Exception{
        aClass=Class.forName("com.entity.User");
        Constructor[] constructors = aClass.getConstructors();
        for (Constructor constructor:constructors){
            System.out.println(constructor);
        }
    }

    /**
     * 获取所有的构造方法,包括私有、公有、受保护
     * @throws Exception
     * 输出:
     * protected com.entity.User(char)
     * private com.entity.User(java.lang.String)
     * public com.entity.User(java.lang.Integer)
     * public com.entity.User()
     */
    @Test
    public void getAllConstructors() throws Exception{
        aClass=Class.forName("com.entity.User");
        Constructor[] constructors = aClass.getDeclaredConstructors();
        for (Constructor constructor:constructors){
            System.out.println(constructor);
        }
    }
}

获取类的成员变量

/**
 * 反射复习3 反射获取类的成员变量
 */
public class ReflectFiled {
    Class aClass;

    /**
     * 获取类的公有的成员变量,并调用
     * @throws Exception
     * 输出:
     * 无参构造器!
     * I love you
     */
    @Test
    public void getFieldPublic() throws Exception {
        aClass=Class.forName("com.entity.User");
        Field username = aClass.getField("username");
        User user= (User) aClass.getConstructor().newInstance();
        username.set(user,"I love you");
        System.out.println(user.username);
    }

    /**
     * 获取类的私有成员变量并调用
     * @throws Exception
     * 输出:
     * 无参构造器!
     * 123123
     */
    @Test
    public void getFiledPrivate() throws Exception{
        aClass=Class.forName("com.entity.User");
        Field password=aClass.getDeclaredField("password");
        password.setAccessible(true);//取消检查
        User user= (User) aClass.getConstructor().newInstance();
        password.set(user,"123123");
        System.out.println(user.getPassword());
    }

    /**
     * 获取类的受保护成员变量并调用
     * @throws Exception
     * 输出:
     * 无参构造器!
     * 12
     */
    @Test
    public void getFieldProtected() throws Exception{
        aClass=Class.forName("com.entity.User");
        Field age=aClass.getDeclaredField("age");
        age.setAccessible(true);//取消检查
        User user= (User) aClass.getConstructor().newInstance();
        age.set(user,12);
        System.out.println(user.getAge());
    }

    /**
     * 获取类的所有公有的成员变量
     * @throws Exception
     * 输出:
     * public java.lang.String com.entity.User.username
     */
    @Test
    public void getAllFieldsPublic() throws Exception{
        aClass=Class.forName("com.entity.User");
        Field[] fields = aClass.getFields();
        for (Field field:fields){
            System.out.println(field);
        }
    }

    /**
     * 获取类的所有的成员变量,包括公有和私有
     * @throws Exception
     * 输出:
     * public java.lang.String com.entity.User.username
     * private java.lang.String com.entity.User.password
     * protected java.lang.Integer com.entity.User.age
     */
    @Test
    public void getAllFileds() throws Exception{
        aClass=Class.forName("com.entity.User");
        Field[] fields = aClass.getDeclaredFields();
        for (Field field:fields){
            System.out.println(field);
        }
    }
}

获取类的方法

public class ReflectMethod {
    Class aClass;

    /**
     * 获取类的公有的方法getAge(),并获取成员变量age复制,使用得到的方法输出
     * @throws Exception
     * 输出:
     * 无参构造器!
     * 12
     */
    @Test
    public void getMethodPublic() throws Exception {
        aClass=Class.forName("com.entity.User");
        //第一个参数是方法名,第二个参数是方法的参数类型
        Method getAge = aClass.getMethod("getAge", null);
        User user= (User) aClass.getConstructor().newInstance();
        Field field=aClass.getDeclaredField("age");
        field.setAccessible(true);
        field.set(user,12);
        System.out.println(getAge.invoke(user,null));
    }

    /**
     * 获取类的私有的方法并调用
     * @throws Exception
     * 输出:
     * 无参构造器!
     * things=watch TV,count=3
     */
    @Test
    public void getMethodPrivate() throws Exception {
        aClass=Class.forName("com.entity.User");
        Method printThings=aClass.getDeclaredMethod("printThings",String.class,Integer.class);
        printThings.setAccessible(true);
        User user= (User) aClass.getConstructor().newInstance();
        printThings.invoke(user,"watch TV",3);
    }

    /**
     * 获取类的所有的公有的方法,包含继承了的方法
     * @throws Exception
     * 输出:
     * public java.lang.String com.entity.User.getPassword()
     * public java.lang.Integer com.entity.User.getAge()
     * 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()
     */
    @Test
    public void getMethodAllPublic() throws Exception{
        aClass=Class.forName("com.entity.User");
        Method[] methods = aClass.getMethods();
        for (Method method:methods){
            System.out.println(method);
        }
    }

    /**
     * 获取类的所有的方法,这里不含有继承的方法,只含有本类的方法,包括公有、私有、保护
     * @throws Exception
     * 输出:
     * public java.lang.String com.entity.User.getPassword()
     * public java.lang.Integer com.entity.User.getAge()
     * private void com.entity.User.printThings(java.lang.String,java.lang.Integer)
     * protected void com.entity.User.hello()
     */
    @Test
    public void getAllMethods() throws Exception{
        aClass=Class.forName("com.entity.User");
        Method[] declaredMethods = aClass.getDeclaredMethods();
        for(Method method:declaredMethods){
            System.out.println(method);
        }
    }
}

反射获取main方法

public class ReflectMain {
    /**
     * 反射获取类的main方法
     * @throws Exception
     * 输出:
     * I love you
     * so much
     */
    @Test
    public void getMain() throws Exception {
        Class aClass=Class.forName("com.entity.User");
        Method main = aClass.getMethod("main", String[].class);
        //因为是静态的,所以Object可以传null
        main.invoke(null,(Object) new String[]{"I love you", "so much"});
    }
}

反射获取泛型

public class ReflectGenerics {
    /**
     * 反射去掉泛型,泛型会在编译的时候检查,编译之后就不存在了,所以可以利用java的字节流文件得到反射对象再填数据
     * @throws Exception
     * 输出:
     * 2
     * 10
     * I love you so much
     */
    @Test
    public void getGenerics() throws Exception {
        ArrayList<Integer> arrayList=new ArrayList<>();
        arrayList.add(2);
        arrayList.add(10);
        Class clazz=arrayList.getClass();
        Method add = clazz.getMethod("add", Object.class);
        add.invoke(arrayList,"I love you so much");
        for (Object object:arrayList){
            System.out.println(object);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值