Java 反射机制 可以从类路径,类,对象获得类,然后获取这个类的所有信息,并加以运用。简单的来说,反射机制指的是程序在运行时能够获取自身的信息。

 为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念,
    静态编译:在编译时确定类型,绑定对象,即通过。
    动态编译:运行时确定类型,绑定对象。

动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性。

它的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于只直接执行相同的操作。

第一部分:Java 反射机制获取类、成员方法、成员变量、父类、实现的接口和构造方法

总述:

在成员变量、成员方法上是区分本类和本类以上继承的父类或实现的接口,在构造方法,获取接口上,只能获取本类自己的构造方法,或者直接实现的接口。此外,有无Declared的方法获取的结果被限制为 public 修饰

获取类的三种方式:

Class.forName("demo3.Demo3Class1")=
 class demo3.Demo3Class1
 Demo3Class1.class=
 class demo3.Demo3Class1
 demo31.getClass()=
 class demo3.Demo3Class1



obj.getMethods()=获取该类以及所有父类及以上的类的 public 修饰的方法,注意完全的打印方式都有public前缀

obj.getDeclaredMethods()=获取该类(仅该类)的方法,不限制是否 public 修饰

obj.getInterfaces()=获取本类直接实现的接口

obj.getSuperclass()=获取本类的直接父类,默认是Object
class java.lang.Object

获取本类的直接构造函数(无参构造函数默认存在,一旦写了有参构造函,无参构造函数就没了,需要重新写:
Constructor cs[]=obj.getConstructors()=获取本类的直接构造函数,仅限 public 修饰的构造函数
Constructor cs=obj.getConstructor() 

Constructor cs[]=obj.getDeclaredConstructors()=获取本类的直接构造函数,本类所有的构造函数,不限制是否public 修饰
Constructor cs=obj.getDeclaredConstructor();

obj.getFields()=获取本类、本类以上继承的类、实现的接口的被public 修饰的 变量

obj.getDeclaredFields()=获取仅本类的所有变量,不限制是否被 public 修饰

代码:

接口 Demo3Interface.java、实现接口 Demo3Interface.java 的类 Demo3Class1.java,继承Demo3Class1.java的类Demo3Class2.java,测试类 Demo3Test.java

接口类

package demo3;

public interface Demo3Interface {
	int number1=1;
	Integer number2=2;
	void method1(String a);
}

实现接口的类1

package demo3;

public class Demo3Class1 implements Demo3Interface {
	private static final String str1="str1";
	String str2="str2";
	public String str3="str3";

	public Demo3Class1() {
	}
	public Demo3Class1(String a,String b) {
	}
	
	
	public void method1(String a) {
		System.out.println();
	}
	
	private void method2(String a){
		System.out.println();
	}

}

继承类1的类2

package demo3;

public class Demo3Class2 extends Demo3Class1 {
	
	private static final String str1="str1";
	String str2="str2";
	public String str3="str3";
	
	public void method3(String name){
		System.out.println();
	}

}

测试类

package demo3;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import org.junit.Test;

/**
 * 接口 和 实现类的反射关系的探究
 * @author wj
 *
 */
public class Demo3Test {
	/**
	 * 在成员变量、成员方法上是区分本类和本类以上继承的父类或实现的接口,在构造方法,获取接口上,只能获取本类自己的构造方法,或者直接实现的接口
	 */
	@Test
	public void test8(){
		System.out.println("综述:\n在成员变量、成员方法上是区分本类和本类以上继承的父类或实现的接口,在构造方法,获取接口上,只能获取本类自己的构造方法,或者直接实现的接口。此外,有无Declared的方法获取的结果被限制为 public 修饰");
	}
	
	/**
	 * 获取仅本类的所有变量,不限制是否被 public 修饰
	 */
	@Test
	public void test7(){
		Demo3Class2 demo=new Demo3Class2();
		Class<?> obj=demo.getClass();
		Field[] fields=obj.getDeclaredFields();
		System.out.println("obj.getDeclaredFields()=获取仅本类的所有变量,不限制是否被 public 修饰");
		for(Field f:fields){
			System.out.println(f);
		}
		System.out.println();
	}
	
	/**
	 * 获取本类、本类以上继承的类、实现的接口的被public 修饰的 成员变量
	 */
	@Test
	public void test6(){
		System.out.println("获取本类、本类以上继承的类、实现的接口的被public 修饰的 变量:");
		Demo3Class1 demo=new Demo3Class1();
		Class<?> obj=demo.getClass();
		Field[] fields=obj.getFields();
		System.out.println("obj.getFields()=获取本类、本类以上继承的类、实现的接口的被public 修饰的 变量");
		for(Field f:fields){
			System.out.println(f);
		}
		
		Demo3Class2 demo2=new Demo3Class2();
		Class<?> obj2=demo2.getClass();
		Field[] fields2=obj2.getFields();
		System.out.println("obj2.getFields()=获取本类、本类以上继承的类、实现的接口的被public 修饰的 变量");
		for(Field f:fields2){
			System.out.println(f);
		}
		System.out.println();
	}
	
	/**
	 * 获取本类的直接构造函数
	 */
	@Test
	public void test5(){
		System.out.println("获取本类的直接构造函数(无参构造函数默认存在,一旦写了有参构造函,无参构造函数就没了,需要重新写:");
		Demo3Class1 demo=new Demo3Class1();
		Class<?> obj=demo.getClass();
		Constructor<?>[] constructors=obj.getConstructors();
		System.out.println("obj.getConstructors()=获取本类的直接构造函数,仅限 public 修饰的构造函数");
		for(Constructor<?> c:constructors){
			System.out.println(c);
		}
		System.out.println();
		Constructor<?>[] constructors2=obj.getDeclaredConstructors();
		System.out.println("obj.getDeclaredConstructors()=获取本类的直接构造函数,本类所有的构造函数");
		for(Constructor<?> c:constructors2){
			System.out.println(c);
		}
		System.out.println();
	}
	
	
	/**
	 * 获取本类的直接父类,默认是Object
	 */
	@Test
	public void test4(){
		System.out.println("获取本类的直接父类,默认是Object:");
		Demo3Class1 demo=new Demo3Class1();
		Class<?> obj=demo.getClass();
		Class<?> classs=obj.getSuperclass();
		System.out.println("obj.getSuperclass()=获取本类的直接父类,默认是Object");
		System.out.println(classs);
		
		Demo3Class2 demo2=new Demo3Class2();
		Class<?> obj2=demo2.getClass();
		Class<?> classs2=obj2.getSuperclass();
		System.out.println("obj2.getSuperclass()=获取本类的直接父类,默认是Object");
		System.out.println(classs2);
		System.out.println();	
	}
	
	/**
	 * 获取本类实现的接口
	 * Demo3Class1 implements Demo3Interface
	 * Demo3Class2 extends Demo3Class1
	 */
	@Test
	public void test3(){
		System.out.println("获取本类直接实现的接口:");
		System.out.println("Demo3Class1 implements Demo3Interface"
				+ "\nDemo3Class2 extends Demo3Class1");
		Demo3Class1 demo=new Demo3Class1();
		Class<?> obj=demo.getClass();
		Class<?>[] classs=obj.getInterfaces();
		System.out.println("obj.getInterfaces()=获取本类直接实现的接口");
		for(Class<?> c:classs){
			System.out.println(c);
		}
		
		Demo3Class2 demo2=new Demo3Class2();
		Class<?> obj2=demo2.getClass();
		Class<?>[] classs2=obj2.getInterfaces();
		System.out.println("obj.getInterfaces()=获取本类直接实现的接口");
		for(Class<?> c:classs2){
			System.out.println(c);
		}
		System.out.println();	
	}
	
	/**
	 * 获取该类(仅该类)的方法
	 */
	@Test
	public void test2(){
		System.out.println("获取该类(仅该类)的方法:");
		Demo3Class1 demo=new Demo3Class1();
		Class<?> obj=demo.getClass();
		
		Method[] methods=obj.getDeclaredMethods();
		System.out.println("obj.getDeclaredMethods()=获取该类(仅该类)的方法,不限制是否 public 修饰");
		for(Method m:methods){
			System.out.println(m);
		}
		System.out.println();
	}
	
	/**
	 * 获取该类以及所有父类及以上的类的 public 修饰的方法
	 */
	@Test
	public void test1(){
		System.out.println("\n获取该类以及所有父类及以上的类的 public 修饰的方法:");
		Demo3Class1 demo=new Demo3Class1();
		Class<?> obj=demo.getClass();
		
		Method[] methods=obj.getMethods();
		System.out.println("obj.getMethods()=获取该类以及所有父类及以上的类的 public 修饰的方法,注意完全的打印方式都有public前缀");
		for(Method m:methods){
			System.out.println(m);
		}
		System.out.println();
	}
	
	/**
	 * 获取类
	 * 有三种方式
	 */
	@Test
	public void test(){
		System.out.println("获取类的三种方式:");
		Class<?> obj0;
		try {
			obj0 = Class.forName("demo3.Demo3Class1");
			System.out.println("Class.forName(\"demo3.Demo3Class1\")=\n		"+obj0);//class demo3.Demo3Class1
		} catch (ClassNotFoundException e) {}
		
		Class<?> obj1=Demo3Class1.class;
		System.out.println("Demo3Class1.class=\n		"+obj1);//class demo3.Demo3Class1
		
		Demo3Class1 demo31=new Demo3Class1();
		Class<?> obj2=demo31.getClass();
		System.out.println("demo31.getClass()=\n		"+obj2);//class demo3.Demo3Class1
	}
}

结果输出就是

获取类的三种方式:
Class.forName("demo3.Demo3Class1")=
class demo3.Demo3Class1
Demo3Class1.class=
class demo3.Demo3Class1
demo31.getClass()=
class demo3.Demo3Class1


获取该类以及所有父类及以上的类的 public 修饰的方法:
obj.getMethods()=获取该类以及所有父类及以上的类的 public 修饰的方法,注意完全的打印方式都有public前缀

public void demo3.Demo3Class1.method1(java.lang.String)
 public final void java.lang.Object.wait() throws java.lang.InterruptedException
 public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
 public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
 public boolean java.lang.Object.equals(java.lang.Object)
 public java.lang.String java.lang.Object.toString()
 public native int java.lang.Object.hashCode()
 public final native java.lang.Class java.lang.Object.getClass()
 public final native void java.lang.Object.notify()
 public final native void java.lang.Object.notifyAll()




获取该类(仅该类)的方法:

obj.getDeclaredMethods()=获取该类(仅该类)的方法,不限制是否 public 修饰
 public void demo3.Demo3Class1.method1(java.lang.String)
 private void demo3.Demo3Class1.method2(java.lang.String)



获取本类直接实现的接口:

Demo3Class1 implements Demo3Interface
 Demo3Class2 extends Demo3Class1
 obj.getInterfaces()=获取本类直接实现的接口
 interface demo3.Demo3Interface
 obj.getInterfaces()=获取本类直接实现的接口




获取本类的直接父类,默认是Object:

obj.getSuperclass()=获取本类的直接父类,默认是Object
 class java.lang.Object
 obj2.getSuperclass()=获取本类的直接父类,默认是Object
 class demo3.Demo3Class1



获取本类的直接构造函数(无参构造函数默认存在,一旦写了有参构造函,无参构造函数就没了,需要重新写:

obj.getConstructors()=获取本类的直接构造函数,仅限 public 修饰的构造函数
 public demo3.Demo3Class1(java.lang.String,java.lang.String)
 public demo3.Demo3Class1()




obj.getDeclaredConstructors()=获取本类的直接构造函数,本类所有的构造函数

public demo3.Demo3Class1(java.lang.String,java.lang.String)
 private demo3.Demo3Class1(java.lang.String)
 public demo3.Demo3Class1()




获取本类、本类以上继承的类、实现的接口的被public 修饰的 变量:

obj.getFields()=获取本类、本类以上继承的类、实现的接口的被public 修饰的 变量
 public java.lang.String demo3.Demo3Class1.str3
 public static final int demo3.Demo3Interface.number1
 public static final java.lang.Integer demo3.Demo3Interface.number2


obj2.getFields()=获取本类、本类以上继承的类、实现的接口的被public 修饰的 变量

public java.lang.String demo3.Demo3Class2.str3
 public java.lang.String demo3.Demo3Class1.str3
 public static final int demo3.Demo3Interface.number1
 public static final java.lang.Integer demo3.Demo3Interface.number2




obj.getDeclaredFields()=获取仅本类的所有变量,不限制是否被 public 修饰

private static final java.lang.String demo3.Demo3Class2.str1
 java.lang.String demo3.Demo3Class2.str2
 public java.lang.String demo3.Demo3Class2.str3




综述:
在成员变量、成员方法上是区分本类和本类以上继承的父类或实现的接口。

在构造方法,获取接口上,获取父类上,只能获取本类自己的构造方法,或者直接实现的接口,或者自己到直接父类。

此外,有无Declared的方法获取的结果被限制为 public 修饰

//被校验字段举例
//@NotNull
//    private List<String> sellDate;

private void checkDemoessage(DemoMessage msg) {
        if (Objects.isNull(msg)) {
            log.error("DemoMessage#handle,消息不合法,跳过处理。msg={}", msg);
            throw new IllegalArgumentException("msg 为空");
        }

        ArrayList<Field> fileds = Lists.newArrayList(DemoMessage.class.getDeclaredFields());
        if(CollectionUtils.isEmpty(fileds)){
            log.error("DemoMessage#handle,系统异常,跳过处理。msg={}", msg);
            throw new IllegalArgumentException("实体不含成员变量");
        }
        fileds.forEach(field -> {
            try {
                field.setAccessible(true);
                if (field.isAnnotationPresent(javax.validation.constraints.NotNull.class)) {
                    if (field.getName().equals("sellDate")) {
                        if (CollectionUtils.isEmpty(msg.getSellDate()) || CollectionUtils.size(msg.getSellDate()) != SELL_DTE_SIZE) {
                            log.error("DemoMessage#handle,sellDate 字段不合法。msg={}", msg);
                            throw new IllegalArgumentException("sellDate 字段不合法");
                        }
                    } else if (field.getType().equals(String.class)) {
                        if (StringUtils.isBlank((String) field.get(msg))) {
                            log.error("DemoMessage#handle,{} 字段不合法。msg={}", field.getName(), msg);
                            throw new IllegalArgumentException(field.getName() + " 字段不可为空");
                        }
                    } else if (field.getType().equals(Long.class)) {
                        if (Objects.isNull(field.get(msg)) || (Long) field.get(msg) < 0) {
                            log.error("DemoMessage#handle,{} 字段不合法。msg={}", field.getName(), msg);
                            throw new IllegalArgumentException(field.getName() + " 字段不可为空");
                        }
                    } else if (field.getType().equals(Integer.class)) {
                        if (Objects.isNull(field.get(msg)) || (Integer) field.get(msg) < 0) {
                            log.error("DemoMessage#handle,{} 字段不合法。msg={}", field.getName(), msg);
                            throw new IllegalArgumentException(field.getName() + " 字段不可为空");
                        }
                    } else if (field.getType().equals(double.class)) {
                        if (Objects.isNull(field.get(msg)) || (double) field.get(msg) < 0) {
                            log.error("DemoMessage#handle,{} 字段不合法。msg={}", field.getName(), msg);
                            throw new IllegalArgumentException(field.getName() + " 字段不可为空");
                        }
                    }

                }
            } catch (IllegalAccessException e) {
                log.error("DemoMessage#handle,消息检测异常,跳过处理。msg={}", msg, e);
                throw new IllegalArgumentException("消息检测异常");
            }
        });
        
    }