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:私有方法赋值 3、Method的一些常用方法 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} 3、Field的常用方法 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类型 |
---|---|---|---|
public | 1 | volatile | 64 |
private | 2 | transient | 128 |
protected | 4 | native | 256 |
static | 8 | interface | 512 |
final | 16 | abstract | 1024 |
synchronized | 32 | strict | 2048 |