Java反射基础学习笔记


Java反射要学习哪些内容,其实要知道的东西很少,也很简单掌握。主要如下:
第一部分就是要理解什么是反射。只需要知道反射可以获取 类的全部信息,其主要也是用来获取 类的全部信息
第二就是会使用反射。包括如何获取反射类、构造函数、成员变量、成员函数、注解等,以及一些常用方法的使用。

一、Java反射的理解

在不知道一个类的信息时,如何获取其中全部的方法呢?
反射就可以获取其中的全部方法的。
反射通过一系列复杂的方法获取了类的信息。
复杂方法是啥?别着急知道,初接触反射也不需要知道,先学会用,会用就行。
面向面试编程,后续再聊!

二、Java反射的知识

1、如何获取Class类

反射的使用要先有Class类,先要知道如何获取Class类

  • 通过实例化的对象获取

    MyClass myClass = new MyClass();
    Class<?> aClass = myClass.getClass();

  • 通过"类.class"获取

    Class<?> aClass = MyClass.class;

  • 通过类所在的包名获取

    Class<?> aClass = Class.forName(“packageName”);

public class Test1 {
    public static void main(String[] args) throws Exception {
        Object o = new Object();
        Class<?> aClass1 = o.getClass();
        Class<Object> aClass2 = Object.class;
        Class<?> aClass3 = Class.forName("java.lang.Object");
        System.out.println(aClass1);
        System.out.println(aClass2);
        System.out.println(aClass3);
        //输出均为"class java.lang.Object"
    }
}

2、使用Class中的构造方法

知道如何获取反射类的Class后,后面就要探讨怎么用了。先看看怎么通过反射实例化对象。

  • 先创建一个简单的类

    下面的类定义了四个构造函数,后续通过这四个构造函数进行实例化

    public class Apple {
        String color;
        int weight;
        public Apple() {
        }
        public Apple(String color, int weight) {
            this.color = color;
            this.weight = weight;
        }
        private Apple(int weight) {
            this.weight = weight;
        }
        private Apple(String color) {
            this.color = color;
        }
    }
    
  • 使用构造函数

    获取构造函数有2*2种方法:
    获取单个公共构造函数,获取全部公共构造函数,获取单个构造函数(私有也可以),获取全部构造函数(包括私有)。
    构造函数获取后就是实例化了,使用newInstace()方法来实例化,也传入对应的参数。

    import java.lang.reflect.Constructor;
    public class AppleTest {
        public static void main(String[] args) throws Exception {
            Class<Apple> aClass = Apple.class;
            //获取构造函数
            //获取构造函数的目的是为了能够进行反射创建实例
            Constructor<?> constructor1 = aClass.getConstructor();//其中的参数就是要获取的实例
            Object constructorObject1 = constructor1.newInstance(); //获取到构造函数进行新建
            System.out.println(constructorObject1);
            Constructor<?> constructor2 = aClass.getConstructor(String.class, int.class);
            Object constructorObject2 = constructor2.newInstance("red", 22); //获取到构造函数进行新建
            System.out.println(constructorObject2);
            //私有的方法是获取不到的。报错java.lang.NoSuchMethodException
            //Constructor<MyClass> constructor2 = aClass.getConstructor(String.class, int.class, int.class);
            
            //可以通过如下方式来取私有构造函数
            Constructor<?> declaredConstructor1 = aClass.getDeclaredConstructor(String.class);
            declaredConstructor1.setAccessible(true); //强行创建,否则会出现java.lang.IllegalAccessException
            Object declaredConstructorObject1 = declaredConstructor1.newInstance("red");
            System.out.println(declaredConstructorObject1);
            Constructor<?> declaredConstructor2 = aClass.getDeclaredConstructor(int.class);
            declaredConstructor2.setAccessible(true); //强行创建,否则会出现java.lang.IllegalAccessException
            Object declaredConstructorObject2 = declaredConstructor2.newInstance(22);
            System.out.println(declaredConstructorObject2);
            //关于构造函数对象的方法 getName() 获取方法名
    
            //获取全部的构造函数
            for (Constructor<?> declaredConstructor : aClass.getDeclaredConstructors()) {
                System.out.println("declaredConstructor:" + declaredConstructor);
            }
        }
    }
    
  • 输出结果

    Apple{color='null', weight=0}
    Apple{color='red', weight=22}
    Apple{color='red', weight=0}
    Apple{color='null', weight=22}
    declaredConstructor:private com.universe.test1.Apple(java.lang.String)
    declaredConstructor:private com.universe.test1.Apple(int)
    declaredConstructor:public com.universe.test1.Apple(java.lang.String,int)
    declaredConstructor:public com.universe.test1.Apple()
    

3、使用Class中的方法

获取成员方法有2*2种:
获取单个公共的方法,获取全部公共的方法,获取单个方法(包含私有),获取全部方法(包含私有)
获取成员方法有什么用呢?当然是为了用了,那么要怎么使用呢?invoke方法

  • 创建一个简单的类

    public class Util {
        //定义公共和私有的方法
        public void getPublicFun() {
            System.out.println("Util公共方法");
        }
        public String getPublicFun(String desc) {
            System.out.println("Util公共方法:" + desc);
            return desc;
        }
        private void getPrivateFun() {
            System.out.println("Util私有方法");
        }
        private String getPrivateFun(String desc) {
            System.out.println("Util私有方法:" + desc);
            return desc;
        }
    }
    
  • 通过反射使用方法

    import java.lang.reflect.Method;
    import java.util.Arrays;
    
    public class UtilTest {
        public static void main(String[] args) throws Exception {
            Class<Util> aClass = Util.class;
            //获取成员方法有2*2种。获取单个公共的方法,获取全部公共的方法,获取单个方法(包含私有),获取全部方法(包含私有)
            //获取成员方法有什么用呢?当然是为了用了,那么要怎么使用呢?invoke方法
            System.out.println("1、获取成员方法 Method");
            Util utilObject = aClass.getConstructor().newInstance();
            Method method1 = aClass.getMethod("getPublicFun");
            method1.invoke(utilObject);
            Method method2 = aClass.getMethod("getPublicFun",String.class);
            String method2return = (String) method2.invoke(utilObject,"公共方法赋值");
            System.out.println("method2return:"+method2return);
            System.out.println("2、私有成员方法的获取");
            //私有成员函数使用getMethod是获取不到的,报错java.lang.NoSuchMethodException
            //Method method2 = aClass.getMethod("getPrivateFun", String.class); //报错java.lang.NoSuchMethodException
            //私有成员方法通过getDeclaredMethod()获取
            Method declaredMethod1 = aClass.getDeclaredMethod("getPrivateFun");
            declaredMethod1.setAccessible(true); //私有直接赋值报错,需要开启权限。java.lang.IllegalAccessException
            declaredMethod1.invoke(utilObject);
            Method declaredMethod2 = aClass.getDeclaredMethod("getPrivateFun", String.class);
            declaredMethod2.setAccessible(true); //私有直接赋值报错,需要开启权限。java.lang.IllegalAccessException
            String declaredMethod2return = (String) declaredMethod2.invoke(utilObject, "私有方法赋值");
            System.out.println("declaredMethod2return:"+declaredMethod2return);
            System.out.println("3、Method的一些常用方法");
            //Method的一些常用方法
            System.out.println(declaredMethod2.getParameterCount()); //参数个数
            System.out.println(Arrays.toString(declaredMethod2.getParameterTypes())); //参数类型
            System.out.println("4、获取全部的方法");
            for (Method declaredMethod : aClass.getDeclaredMethods()) {
                System.out.println(declaredMethod);
            }
        }
    }
    
  • 输出结果

    1、获取成员方法 Method
    Util公共方法
    Util公共方法:公共方法赋值
    method2return:公共方法赋值
    2、私有成员方法的获取
    Util私有方法
    Util私有方法:私有方法赋值
    declaredMethod2return:私有方法赋值
    3Method的一些常用方法
    1
    [class java.lang.String]
    4、获取全部的方法
    private void com.universe.test1.Util.getPrivateFun()
    private java.lang.String com.universe.test1.Util.getPrivateFun(java.lang.String)
    public void com.universe.test1.Util.getPublicFun()
    public java.lang.String com.universe.test1.Util.getPublicFun(java.lang.String)
    

4、使用Class中的属性

获取成员的有2*2种方法:
获取单个的公共成员,获取全部的公共成员,获取单个的成员(私有也可以),获取全部的成员(私有也可以)
为什么要获得成员呢,当然是为了用

  • 先创建一个类

    public class User {
        public String name;
        private int age;
        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
  • 通过反射获取成员变量

    import java.lang.reflect.Field;
    public class UserTest {
        public static void main(String[] args) throws Exception {
            Class<User> aClass = User.class;
            System.out.println("获取成员Field的部分");
            //1、获取公共的成员
            System.out.println("1、获取公共的成员");
            User userObject = (User) aClass.getConstructor().newInstance(); //先创建一个实例,用于后续赋值
            Field field1 = aClass.getField("name");
            field1.set(userObject, "tang"); //成员赋值,使用set
            System.out.println(userObject);
            //2、获取私有的成员
            System.out.println("2、获取私有的成员");
            //Field field2 = aClass.getField("age"); //私有成员通过getField是获取不到的,				 
            //报错java.lang.NoSuchFieldException
            Field declaredField1 = aClass.getDeclaredField("age");
            declaredField1.setAccessible(true); //私有成员直接赋值报错。java.lang.IllegalAccessException
            declaredField1.set(userObject, 22);
            System.out.println(userObject);
            //3、Field的常用方法
            System.out.println("3、Field的常用方法");
            System.out.println(field1.getName()); //获取成员的名字 name
            System.out.println(field1.getType()); //获取成员的类型 class java.lang.String
            //4、获取全部的成员
            System.out.println("4、获取全部的成员");
            for (Field declaredField : aClass.getDeclaredFields()) {
                System.out.println("declaredField:"+declaredField);
            }
        }
    }
    
  • 输出结果

    获取成员Field的部分
    1、获取公共的成员
    User{name='tang', age=0}
    2、获取私有的成员
    User{name='tang', age=22}
    3Field的常用方法
    name
    class java.lang.String
    4、获取全部的成员
    declaredField:public java.lang.String com.universe.test1.User.name
    declaredField:private int com.universe.test1.User.age
    

5、使用Class中的注解

通过反射获取注解可是十分重要的内容,目前主流的java框架都在使用注解。
反射使用注解主要有几个方面:
1、如果获取注解呢?获取不到怎么使用呢?使用getAnnotations()
2、也可判断是有没有某个注解。使用isAnnotationPresent()
3、获取到的注解中的方法是可以直接使用的哦

  • 使用注解反射

    import java.lang.annotation.Documented;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.util.Arrays;
    
    public class AnnotationTest {
        public static void main(String[] args) {
            Class<MyBean> myBeanClass = MyBean.class;
            System.out.println(Arrays.toString(myBeanClass.getAnnotations())); //获取全部的注解
            System.out.println(myBeanClass.isAnnotationPresent(Desc.class)); //判断有没有某个注解
            Desc desc = myBeanClass.getAnnotation(Desc.class); //可以直接获取到对应的注解
            System.out.println(desc.myDesc()); //注解方法的调用
        }
    }
    @Documented
    @Retention(RetentionPolicy.RUNTIME) //编译器将Annotation存储于class文件中,这样才能使用反射获取
    @interface Desc {
        String myDesc() default "This is an annotation!";
    }
    
    @Desc(myDesc = "Class MyBean is used!")
    class MyBean {
        String name;
    }
    
  • 输出结果

    [@com.universe.test1.Desc(myDesc="Class MyBean is used!")]
    true
    Class MyBean is used!
    

6、Class中的常用方法

通过反射可以获取类的所有信息,想要什么就去找吧

Class<Object> aClass = Object.class;
System.out.println(aClass.getPackage()); //package java.lang
System.out.println(aClass.getPackageName()); //java.lang
System.out.println(aClass.getName()); //java.lang.Object
System.out.println(aClass.getSimpleName()); //Object
System.out.println(aClass.getModifiers()); //1
Class<HashMap> hashMapClass = HashMap.class;
System.out.println(aClass.isAssignableFrom(hashMapClass));
System.out.println(hashMapClass.isAssignableFrom(aClass));
Class<? super HashMap> superclass = hashMapClass.getSuperclass();//获取该类继承的类
System.out.println(superclass); //class java.util.AbstractMap
Class<?>[] interfaces = hashMapClass.getInterfaces(); //获取该类实现的接口
System.out.println(interfaces.length); //3
for (Class<?> anInterface : interfaces) {
    System.out.println(anInterface.toString());
}
//interface java.util.Map
//interface java.lang.Cloneable
//interface java.io.Serializable
  • getModifiers()方法返回int类型值表示该字段的修饰符。当没有类型时,对应的INT类型是0。
修饰符对应的INT类型修饰符对应的INT类型
public1volatile64
private2transient128
protected4native256
static8interface512
final16abstract1024
synchronized32strict2048
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值