Java反射基础知识
- 一、Java反射的理解
- 二、Java反射的知识
- 1、如何获取Class类
- 2、使用Class中的构造方法
- 3、使用Class中的方法
- 4、使用Class中的属性
- 5、使用Class中的注解
- 6、Class中的常用方法
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.IllegalAccessExceptionObject declaredConstructorObject1 = declaredConstructor1.newInstance("red");System.out.println(declaredConstructorObject1);Constructor<?> declaredConstructor2 = aClass.getDeclaredConstructor(int.class);declaredConstructor2.setAccessible(true); //强行创建,否则会出现java.lang.IllegalAccessExceptionObject 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.IllegalAccessExceptiondeclaredMethod1.invoke(utilObject);Method declaredMethod2 = aClass.getDeclaredMethod("getPrivateFun", String.class);declaredMethod2.setAccessible(true); //私有直接赋值报错,需要开启权限。java.lang.IllegalAccessExceptionString 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;@Overridepublic 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"); //成员赋值,使用setSystem.out.println(userObject);//2、获取私有的成员System.out.println("2、获取私有的成员");//Field field2 = aClass.getField("age"); //私有成员通过getField是获取不到的, //报错java.lang.NoSuchFieldExceptionField declaredField1 = aClass.getDeclaredField("age");declaredField1.setAccessible(true); //私有成员直接赋值报错。java.lang.IllegalAccessExceptiondeclaredField1.set(userObject, 22);System.out.println(userObject);//3、Field的常用方法System.out.println("3、Field的常用方法");System.out.println(field1.getName()); //获取成员的名字 nameSystem.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 |