Java 基础-反射

时间:2022-02-27 04:52:02

反射-Reflect

测试用到的代码

1.接口 Person.java

 public interface Person {
Boolean isMale = true; void say(); void eat(); void sleep();
}

2. Man.java

 public class Man implements Person {
private String name;
private int age; public Man() {
} public Man(String name) {
this.name = name;
} public Man(int age) {
this.age = age;
} public Man(String name, int age) {
this.name = name;
this.age = age;
} private String test1(String name, int age) {
return name + String.valueOf(age);
} @Override
public void say() {
System.out.println("I am Man");
} public void sayName(String name) {
System.out.println("I am " + name);
} public static void sayStatic() {
System.out.println("This is a static method");
} public static void sayStatic2(String name) {
System.out.println("This is a static method,I am " + name);
} @Override
public void eat() {
System.out.println("Man eat 5 breads");
} @Override
public void sleep() {
System.out.println("Man need sleep 8 hours");
} @Override
public String toString() {
return this.name + ":" + this.age;
}
}

3. Women.java

 public class Women implements Person {
@Override
public void say() {
System.out.println("I am women");
} @Override
public void eat() {
System.out.println("Women eat 3 breads");
} @Override
public void sleep() {
System.out.println("Women sleep 8 hours");
}
}

4. Child.java

 public class Child extends Man {

     @Override
public void say() {
System.out.println("I am Child");
}
}

通过反射,获取到类的信息和操作

1.获取到类完整的包名和类名

 public class ReflectTest {
public static void main(String[] args) {
Class<?> c = Man.class;
String name = c.getName();
System.out.println(name);
}
}

结果:

cc.lijingbo.script.reflect.Man

2.实例化 Class 类对象,有三种方法可以获取到 Class 对象。

 public class ReflectTest {
public static void main(String[] args) {
Class<?> c1 = null;
Class<?> c2 = null;
Class<?> c3 = null; c1 = Man.class;
Man man = new Man();
c2 = man.getClass();
try {
c3 = Class.forName("cc.lijingbo.script.reflect.Man");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} System.out.println("类的名称:" + c1.getName());
System.out.println("类的名称:" + c2.getName());
System.out.println("类的名称:" + c3.getName());
}
}

结果:

类的名称:cc.lijingbo.script.reflect.Man
类的名称:cc.lijingbo.script.reflect.Man
类的名称:cc.lijingbo.script.reflect.Man

3. Class 类实例化 Man 类,通过 Man 类的无参构造方法

 public class ReflectTest {
public static void main(String[] args) {
Class<?> c3 = null;
try {
c3 = Class.forName("cc.lijingbo.script.reflect.Man");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
Man man = (Man) c3.newInstance();
man.say();
man.eat();
man.sleep();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}

结果:

I am Man
Man eat 5 breads
Man need sleep 8 hours

[注意]:假如类中定义了构造方法,且没有无参构造方法,使用 newInstance() 会报错,无法实例化。

Man.java 去掉无参构造方法,然后使用 Class 类实例化 Man 类

Test.java

 public class ReflectTest {
public static void main(String[] args) {
Class<?> c3 = null;
try {
c3 = Class.forName("cc.lijingbo.script.reflect.Man");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
Man man = (Man) c3.newInstance();
man.say();
man.eat();
man.sleep();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
 

结果:

 java.lang.InstantiationException: cc.lijingbo.script.reflect.Man
at java.lang.Class.newInstance(Class.java:423)
at cc.lijingbo.script.reflect.ReflectTest.main(ReflectTest.java:15)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: java.lang.NoSuchMethodException: cc.lijingbo.script.reflect.Man.<init>()
at java.lang.Class.getConstructor0(Class.java:3074)
at java.lang.Class.newInstance(Class.java:408)
... 6 more

分析:

可以看到异常的是原因: Caused by: java.lang.NoSuchMethodException: cc.lijingbo.script.reflect.Man.<init>(),并重新抛出了 java.lang.InstantiationException的异常。引起的原因就是没有无参构造方法造成的。

4. 调用 Man 类中的所有构造方法,可以通过各种构造方法实例化 Man 类。

[注意]:反射获取到的所有构造方法中,注意在数组中的顺序。

Test.java

 public class ReflectTest {
public static void main(String[] args) {
Class<?> c = null;
try {
c = Class.forName("cc.lijingbo.script.reflect.Man");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Man m1 = null;
Man m2 = null;
Man m3 = null;
Man m4 = null;
Constructor<?>[] constructors = c.getConstructors();
try {
m1 = (Man) constructors[3].newInstance();
m2 = (Man) constructors[2].newInstance("Jerome");
m3 = (Man) constructors[1].newInstance(20);
m4 = (Man) constructors[0].newInstance("Jerome1", 21);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
System.out.println(m1);
System.out.println(m2);
System.out.println(m3);
System.out.println(m4);
}
}

结果:

null:0
Jerome:0
null:20
Jerome1:21

5. 获得 Man 类中的全部构造函数

 public class ReflectTest {
public static void main(String[] args) {
Class<?> c = null;
try {
c = Class.forName("cc.lijingbo.script.reflect.Man");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Constructor<?>[] constructors = c.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
}
}

结果:

 public cc.lijingbo.script.reflect.Man(java.lang.String,int)
public cc.lijingbo.script.reflect.Man(int)
public cc.lijingbo.script.reflect.Man(java.lang.String)
public cc.lijingbo.script.reflect.Man()

 

6. 返回类实现的接口

 public class ReflectTest {
public static void main(String[] args) {
Class<?> c = null;
try {
c = Class.forName("cc.lijingbo.script.reflect.Man");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Class<?>[] interfaces = c.getInterfaces();
for (Class in : interfaces) {
System.out.println(in.getName());
}
}
}

结果:

cc.lijingbo.script.reflect.Person

7. 取得 Child 类的父类

Child.java

 public class Child extends Man {

     @Override
public void say() {
System.out.println("I am Child");
}
}

Test.java

 public class ReflectTest {
public static void main(String[] args) {
Class<?> c = null;
try {
c = Class.forName("cc.lijingbo.script.reflect.Child");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Class<?> superclass = c.getSuperclass();
System.out.println(superclass.getName());
}
}

结果:

cc.lijingbo.script.reflect.Man

8.  获取构造方法的修饰符

 public class ReflectTest {
public static void main(String[] args) {
Class<?> c = null;
try {
c = Class.forName("cc.lijingbo.script.reflect.Man");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Constructor<?>[] constructors = c.getConstructors();
for (int i = 0; i < constructors.length; i++) {
Class[] parameterTypes = constructors[i].getParameterTypes();
int modifiers = constructors[i].getModifiers();
System.out.print(Modifier.toString(modifiers) + " ");
System.out.print(constructors[i].getName());
System.out.println("(");
for (int j = 0; j < parameterTypes.length; ++j) {
System.out.print(parameterTypes[j].getName() + " arg" + i);
if (j < parameterTypes.length - 1) {
System.out.print(",");
}
}
System.out.println("){}");
}
}
}

结果:

 public cc.lijingbo.script.reflect.Man(
java.lang.String arg0,int arg0){}
public cc.lijingbo.script.reflect.Man(
int arg1){}
public cc.lijingbo.script.reflect.Man(
java.lang.String arg2){}
public cc.lijingbo.script.reflect.Man(
){}

9. 取得 Man 类的全部属性

 public class ReflectTest {
public static void main(String[] args) {
Class<?> c = null;
try {
c = Class.forName("cc.lijingbo.script.reflect.Man");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Field[] declaredFields = c.getDeclaredFields();
for (Field field : declaredFields) {
int modifiers = field.getModifiers();
String type = Modifier.toString(modifiers);
Class<?> fieldType = field.getType();
System.out.println(type + " " + fieldType + " " + field.getName());
}
System.out.println("..........");
Field[] fields = c.getFields();
for (Field field : fields) {
int modifiers = field.getModifiers();
String type = Modifier.toString(modifiers);
Class<?> fieldType = field.getType();
System.out.println(type + " " + fieldType + " " + field.getName());
}
}
}

结果:

private class java.lang.String name
private int age
..........
public static final class java.lang.Boolean isMale

10.调用 Man 类中的方法,有参方法,无参方法,静态无参方法和静态有参方法

 public class ReflectTest {
public static void main(String[] args) {
Class<?> c = null;
try {
c = Class.forName("cc.lijingbo.script.reflect.Man");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} //调用带参的方法
try {
Method sayName = c.getMethod("sayName", String.class);
sayName.invoke(c.newInstance(), "Jerome");
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} //调用无参的方法
try {
Method say = c.getMethod("say");
say.invoke(c.newInstance());
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} //调用静态无参方法
try {
Method sayStatic = c.getMethod("sayStatic");
sayStatic.invoke(null);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} //调用静态带参方法
try {
Method sayStatic2 = c.getMethod("sayStatic2", String.class);
sayStatic2.invoke(null,"Jerome");
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} }
}

结果:

I am Jerome
I am Man
This is a static method
This is a static method,I am Jerome

11. 获取到 Man 类所有的方法,及方法的修饰符,返回值和参数

 public class ReflectTest1 {
public static void main(String[] args) {
Class<?> c = Man.class;
Method[] methods = c.getDeclaredMethods();
for (Method method : methods) {
StringBuffer sb = new StringBuffer();
//获取到方法的修饰符
String modifier = Modifier.toString(method.getModifiers());
sb.append(modifier + " ");
Class<?> methodReturnType = method.getReturnType();
//获取到方法的返回类型,没有返回值时为null
String returnType = methodReturnType.getName();
String methodName = method.getName();
if (returnType == null) {
sb.append("void ");
} else {
sb.append(returnType + " ");
}
sb.append(methodName).append("(");
Class<?>[] parameterTypes = method.getParameterTypes();
for (Class parameter : parameterTypes) {
String name = parameter.getName();
sb.append(name).append(",");
}
sb.append(")");
System.out.println(sb.toString());
}
}
}

结果:

public java.lang.String toString()
public void sleep()
public void say()
private java.lang.String test1(java.lang.String,int,)
public static void sayStatic()
public void eat()
public void sayName(java.lang.String,)
public static void sayStatic2(java.lang.String,)

12. 获取到类加载器

 public class ReflectTest2 {
public static void main(String[] args) {
Class<?> c = Man.class;
//获取到 classloader
ClassLoader classLoader = c.getClassLoader();
//通过获取到classloader的类类型,得到classloader的名称
String name = classLoader.getClass().getName();
System.out.println(name);
}
}

结果:

sun.misc.Launcher$AppClassLoader

13. 修改成员变量的值

 public class ReflectTest3 {
public static void main(String[] args) {
Class<?> c = Man.class;
try {
Field name = c.getDeclaredField("name");
name.setAccessible(true);
Object o = c.newInstance();
name.set(o,"Haha");
System.out.println(name.get(o));
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}

结果:

Haha

14. 获取数组相关信息

 public class ReflectTest4 {
public static void main(String[ ] args){
int[] temp = {1,2,4,5,7};
Class<?> c = temp.getClass();
Class<?> componentType = c.getComponentType();
System.out.println("数组的类型:"+componentType.getName());
System.out.println("数组的长度:"+Array.getLength(temp));
System.out.println("数组第三个位置:"+Array.get(temp,2));
Array.set(temp,2,44);
System.out.println("修改后的数组第三个位置:"+Array.get(temp,2));
}
}

结果:

数组的类型:int
数组的长度:5
数组第三个位置:4
修改后的数组第三个位置:44