Java基础(九)--反射

什么是反射?

  在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性

  这种动态获取的信息以及动态调用对象的方法的功能称为反射机制。

反射的前提:

  需要获取代表每个类的java.lang.class对象,对于HotSpot来说,这个class对象保存在在方法区,作为这个类的各种数据的访问入口

获取class对象的方式:

public static void main(String[] args) throws Exception{
	//第一种,通过对象获取class对象
	A a = new A();
	Class aClass = a.getClass();
	System.out.println(aClass.getName());

	//第二种,通过类直接获取class对象
	Class aClass1 = A.class;
	System.out.println(aClass == aClass1);

	//第三种,通过类的全限定名获取class对象(包名+类名)
	Class aClass2 = Class.forName("com.it.exception.A");
	System.out.println(aClass == aClass2);
}

PS: 一般使用第三种方式来获取

构造函数相关方法:

public class A {
    public A(int i) {
        System.out.println("A Constructor " + i);
    }

    public A() {
        System.out.println("A Constructor No Parameter");
    }

    protected A(String name) {
        System.out.println("A Constructor " + name);
    }

    private A(int i, String name) {
        System.out.println("A Constructor " + i + " name " + name);
    }
}
public static void main(String[] args) throws Exception{
	Class aClass = Class.forName("com.it.exception.A");

	//返回所有public构造函数
	Constructor[] constructors1 = aClass.getConstructors();
	for (Constructor constructor : constructors1) {
		System.out.println(constructor);
	}
	System.out.println("----getConstructors---------");
	//返回具体某种参数类型的public构造函数,参数也可以是null,表示无参构造器
	Constructor constructor = aClass.getConstructor(int.class);
	System.out.println(constructor);
	System.out.println("----get int Constructors---------");

	//返回所有构造函数,无论什么修饰符修饰
	Constructor[] constructors2 = aClass.getDeclaredConstructors();
	for (Constructor constructor1 : constructors2) {
		System.out.println(constructor1);
	}
	System.out.println("----getDeclaredConstructors---------");

	//返回具体某种参数类型的构造函数,无论什么修饰符修饰
	Constructor constructor2 = aClass.getDeclaredConstructor(String.class);
	System.out.println(constructor2);
	System.out.println("----String getDeclaredConstructor---------");
}

结果:

public com.it.exception.A()
public com.it.exception.A(int)
----getConstructors---------
public com.it.exception.A(int)
----get int Constructors---------
private com.it.exception.A(int,java.lang.String)
protected com.it.exception.A(java.lang.String)
public com.it.exception.A()
public com.it.exception.A(int)
----getDeclaredConstructors---------
protected com.it.exception.A(java.lang.String)

getEnclosingConstructor:

public class Outter {
    public void destination(String s) {
        class Inner1 {
            private String label;
            public Inner1() {
                System.out.println("abc");
            }
            public Inner1(String whereTo) {
                this.label = whereTo;
            }
        }
        Class aClass = new Inner1().getClass();
        //获取局部或匿名内部类在定义时所在的构造器
        System.out.println(aClass.getEnclosingConstructor());
    }

    public static void main(String[] args) {
        Outter outter = new Outter();
        outter.destination("aaa");
    }

}

这里实验类局部内部类一直得到的是null,大家可以试一下

调用构造器:

constructor.newInstance(); //默认无参构造器

字段相关方法:

public class A {
    private int id;
    private String name;
    public int sex;

}
public static void main(String[] args) throws Exception{
	Class aClass = Class.forName("com.it.exception.A");
	//获取所有public字段
	Field[] fields = aClass.getFields();
	for (Field field : fields) {
		System.out.println(field);
	}
	//获取某个具体字段,这个字段必须是public修饰,否则会报错
	Field field = aClass.getField("sex");
	System.out.println(field);
	//获取所有字段,无论修饰符
	Field[] fields1 = aClass.getDeclaredFields();
	for (Field field1 : fields1) {
		System.out.println(field1);
	}
	//获取某个具体字段
	Field field1 = aClass.getDeclaredField("id");
	System.out.println(field1);
}

结果:

public int com.it.exception.A.sex
public int com.it.exception.A.sex
private int com.it.exception.A.id
private java.lang.String com.it.exception.A.name
public int com.it.exception.A.sex
private int com.it.exception.A.id

其余操作:

public static void main(String[] args) throws Exception{
	Class aClass = Class.forName("com.it.exception.A");
	Field field = aClass.getDeclaredField("name");
	Object object = aClass.getDeclaredConstructor(null).newInstance();
	field.setAccessible(true); //设置为true,private字段可以修改,私有字段必须设置为true,否则set字段会发生异常
	field.set(object, "sam");//设置具体字段value
	A a = (A)object;
	System.out.println(a.toString());
}

结果:

A(id=0, name=sam, sex=0)

方法相关操作:

public class A {
    private int id;
    private String name;
    public int sex;

    public void add() {
        System.out.println("add()");
    }

    private void del() {
        System.out.println("del()");
    }

    public static void update() {
        System.out.println("static update()");
    }
}
public static void main(String[] args) throws Exception{
	Class aClass = Class.forName("com.it.exception.A");
	Method[] methods = aClass.getMethods();
	//获取所有public字段
	for (Method method : methods) {
		System.out.println(method);
	}
	//获取某个具体方法,这个method必须是public修饰,否则会报错
	Method method = aClass.getMethod("add", null);
	System.out.println(method);

	//获取所有字段,无论修饰符
	Method[] methods1 = aClass.getDeclaredMethods();
	for (Method method1 : methods1) {
		System.out.println(method1);
	}

	//获取某个具体字段
	Method method1 = aClass.getDeclaredMethod("del", null);
	System.out.println(method1);
}

结果:已经省略默认继承object的相关方法

public void com.it.exception.A.add()
public static void com.it.exception.A.update()

public void com.it.exception.A.add()

public void com.it.exception.A.add()
public static void com.it.exception.A.update()
private void com.it.exception.A.del()

private void com.it.exception.A.del()

其余操作:

private int del(int i) {
	System.out.println("del(): " + i);
	return i + 3;
}
public static void main(String[] args) throws Exception{
	Class aClass = Class.forName("com.it.exception.A");
	Object object = aClass.getDeclaredConstructor(null).newInstance();
	Method method = aClass.getDeclaredMethod("del", int.class);
	method.setAccessible(true);
	Object object1 = method.invoke(object, 20);
	System.out.println(object1);
}

结果:

del(): 20
23

其他:

public class A extends B implements C{

    @Override
    public void f() throws IOException {
        System.out.println("f()");
    }
}
public static void main(String[] args) throws Exception{
	Class aClass = Class.forName("com.it.exception.A");
	System.out.println(aClass.getSuperclass());// 获取父类Class对象
	System.out.println(aClass.getClassLoader());// 获取类的加载器
	System.out.println(aClass.getInterfaces()[0]);// 获取类的接口数组列表

	A[] as = new A[1];
	System.out.println(as.getClass().getComponentType());// 获取该数组的Class对象

	System.out.println(aClass.getPackage().getName());// 获取包
}

结果:

class com.it.exception.B
sun.misc.Launcher$AppClassLoader@18b4aac2
interface com.it.exception.C
class com.it.exception.A
com.it.exception

通过反射越过泛型检查

public static void main(String[] args) throws Exception{
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
//        List<String> list = Arrays.asList("a", "b");
        Class aClass = list.getClass();
        Method method = aClass.getMethod("add", Object.class);
        method.invoke(list, 20);
        System.out.println(list);
//        list.forEach(s -> {
//            System.out.println(s);
//        });
    }

结果:List<String> list = Arrays.asList("a", "b");然后执行invoke()会报错的,也不要使用foreach也会报错(ClassCastException)

posted @ 2019-06-14 16:01  Diamond-Shine  阅读(215)  评论(0编辑  收藏  举报