在不知道一个类的信息时,如何获取其中全部的方法呢?
反射就可以获取其中的全部方法的。
反射通过一系列复杂的方法获取了类的信息。
复杂方法是啥?别着急知道,初接触反射也不需要知道,先学会用,会用就行。
面向面试编程,后续再聊!
反射的使用要先有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"
}
}
知道如何获取反射类的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()
获取成员方法有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)
获取成员的有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
通过反射获取注解可是十分重要的内容,目前主流的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!
通过反射可以获取类的所有信息,想要什么就去找吧
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
修饰符 | 对应的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 |