转载和引用,请注明原文出处! Fork me on GitHub
结局很美妙的事,开头并非如此!

反射

一、什么是反射

        java程序在运行期间能够动态加载、解析、使用一些在编译阶段并不确定的数据类型   

二、反射的功能

       2.1、加载运行时才能确定的数据类型
       2.2、解析类的结构,获取内部信息
       2.3、操作该类型或其实例:访问属性、调用方法、创建新对象

package com.study.test;

import static java.lang.System.out;

class aaa {

    void test() {
        out.println("您好!");
    }
}

public class ClassLoaderJZ {

    public static void main(String[] args) throws Exception {
        // 反射的概览
        // 传统的实现test方法的调用通过如下方式
        aaa a1 = new aaa();
        a1.test();
        // 通过反射来实现test方法的调用
        aaa.class.newInstance().test();// 获取类模板调用方法实例化对象,最后调用test方法,更加简洁

        // 返回默认的无参构造函数 返回类型为数组
        out.println(aaa.class.getDeclaredConstructors()[0]);
        out.println(aaa.class.getSuperclass());// 返回aaa的父类Object

        // 输出为空可知Object已经是最高的父类了,不能再回溯了
        out.println(aaa.class.getSuperclass().getSuperclass());
    }

}

三、获取Class对象的方法

       3.1、Class的静态函数forName()获取

       3.2、调用从Object继承下来的getClass()函数

       3.3、通过.class表达式获取

package com.study.test;

import static java.lang.System.out;

class aaa {

    void test() {
        out.println("您好!");
    }
}

public class ClassLoaderJZ {

    public static void main(String[] args) throws Exception {
        // 获取Class对象的途径
        // 针对引用数据类型 
        //1、Class的静态函数forName()获取
        Class<?> c1 = Class.forName("com.study.test.aaa");
        out.println(c1);
        // 2、调用从Object继承下来的getClass()函数
        aaa a1 = new aaa();
        Class<?> c2 = a1.getClass();
        out.println(c2);
        // 3、通过.class表达式获取
        out.println(aaa.class);
        Class<aaa> c3 = aaa.class;
        out.println(c3);

        // 针对基本数据类型及void
        // 通过TYPE属性得到包装类的基本类型
        int i = 1;// 栈区存储 基本类型
        Integer j = new Integer(1);// 堆区存储 包装类 等于Integer j=1;
        Class<Integer> c4 = Integer.TYPE;// 输出int 返回包装类的基本类型
        out.println(c4);

        // 使用.class 表达式
        Class c5 = int.class;
        Class c6 = double.class;
        Class c7 = void.class;
        out.println(c5);
        out.println(c6);
        out.println(c7);
    }

}

四、反射操作构造函数

      4.1 调用无参、有一个参数、有多个参数的构造函数实例化对象

package com.study.test;

import static java.lang.System.out;

import java.lang.reflect.Constructor;

class aaa {
    aaa() {
        out.println("aaa()");
    }

    aaa(int i) {
        out.println("aaa(int i)");
    }

    aaa(int i, String j) {
        out.println("aaa(int i,String j)");
    }

    void test() {
        out.println("void test()");
    }

}

public class ClassLoaderJZ {

    public static void main(String[] args) throws Exception {
        // 通过反射我们获得了构造函数的规则 我们获得的是构造函数的数组
        out.println(aaa.class.getDeclaredConstructors().length);
        // out.println(aaa.class.getDeclaredConstructors()[0].newInstance());
        // out.println(aaa.class.getDeclaredConstructors()[1].newInstance(1));
        // 遍历输出构造函数 默认按参数个数的多少由大到小一次输出
        for (Constructor<?> c1 : (aaa.class.getDeclaredConstructors())) {
            out.println(c1);

        }
        // 怎样通过反射实例化调用函数?
        // aaa.class.newInstance().test(new int[]{4,5,6});
        // 错的aaa.class.getDeclaredConstructors()[0].newInstance(1);

        // //传统方案调用test
        // aaa a1=new aaa();
        // a1.test(new int[]{1,2,3});

        // 调用无参的构造函数动态生成实例
        // aaa.class.newInstance().test();
        aaa.class.getDeclaredConstructors()[2].newInstance();
        // 调用带一个参数构造函数生成实例
        aaa.class.getDeclaredConstructors()[1].newInstance(1);

        // 调用带两个参数构造函数生成实例
        aaa.class.getDeclaredConstructors()[0].newInstance(1, "abc");

    }

}

输出结果:

3
com.study.test.aaa(int,java.lang.String)
com.study.test.aaa(int)
com.study.test.aaa()
aaa()
aaa(int i)
aaa(int i,String j)

4.2  获取构造函数的修饰符、名字、以及参数

package com.study.test;

import static java.lang.System.out;

import java.lang.reflect.Constructor;

class aaa {
    aaa() {
        out.println("aaa()");
    }

    aaa(int i) {
        out.println("aaa(int i)");
    }

    aaa(int i, String j) {
        out.println("aaa(int i,String j)");
    }

    void test() {
        out.println("void test()");
    }

}

public class ClassLoaderJZ {

    public static void main(String[] args) throws Exception {
        // 通过反射我们获得了构造函数的规则 我们获得的是构造函数的数组
        out.println(aaa.class.getDeclaredConstructors().length);
        // out.println(aaa.class.getDeclaredConstructors()[0].newInstance());
        // out.println(aaa.class.getDeclaredConstructors()[1].newInstance(1));
        // 遍历输出构造函数 默认按参数个数的多少由大到小一次输出
        // getConstructors()函数获取public的构造函数;getDeclaredConstructors()获取所有的构造函数
        for (Constructor<?> c1 : (aaa.class.getDeclaredConstructors())) {
            // 获取构造函数的修饰符、名字、参数类型
            out.println("获取构造函数的修饰符、名字、参数类型");
            out.println(c1.getModifiers());
            out.println(c1.getName());
            for (Class c2 : c1.getParameterTypes()) {
                out.println(c2);
            }
        }

    }

}

输出结果:

3
获取构造函数的修饰符、名字、参数类型
0
com.study.test.aaa
int
class java.lang.String
获取构造函数的修饰符、名字、参数类型
0
com.study.test.aaa
int
获取构造函数的修饰符、名字、参数类型
0
com.study.test.aaa

五、反射获取接口.

package com.study.test;

import static java.lang.System.out;

interface I1 {

}

interface I2 {

}

class aaa implements I1, I2 {
    public aaa() {
        out.println("aaa()");
    }

    private aaa(int i) {
        out.println("aaa(int i)");
    }

    protected aaa(int i, String j) {
        out.println("aaa(int i,String j)");
    }

    void test() {
        out.println("void test()");
    }

}

public class ClassLoaderJZ {

    public static void main(String[] args) throws Exception {

        // 获取接口
        out.println("获取接口");
        for (Class<?> c2 : aaa.class.getInterfaces()) {
            out.println(c2);
        }

    }

}

输出结果:

获取接口
interface com.study.test.I1
interface com.study.test.I2

六、反射获取方法的返回类型,修饰符,参数类型等等

package com.study.test;

import static java.lang.System.out;

import java.lang.reflect.Method;

interface I1 {

}

interface I2 {

}

class aaa implements I1, I2 {
    public aaa() {
        out.println("aaa()");
    }

    private aaa(int i) {
        out.println("aaa(int i)");
    }

    protected aaa(int i, String j) {
        out.println("aaa(int i,String j)");
    }

    void test() throws Exception {
        out.println("void test()");
    }

    void test1() {
        out.println("void test1()");
    }

    void test2() {
        out.println("void test2()");
    }

}

public class ClassLoaderJZ {

    public static void main(String[] args) throws Exception {

        // getMethod()方法获得所有public的方法包括从Object继承的方法
        // for(Method m:aaa.class.getMethods()){
        // out.println(m);
        // };
        // getDeclaredMethods()方法获得所有在本类中自己声明的方法
        for (Method m : aaa.class.getDeclaredMethods()) {
            out.println("输出方法的返回类型,参数类型,修饰符,以及方法的异常类型");

            out.println(m.getReturnType());
            out.println(m.getParameters().length);
            out.println(m.getModifiers());
            for (Class c : m.getExceptionTypes()) {
                out.println(m);
            }

        }

    }

}

输出结果:

输出方法的返回类型,参数类型,修饰符,以及方法的异常类型
void
0
0
void com.study.test.aaa.test() throws java.lang.Exception
输出方法的返回类型,参数类型,修饰符,以及方法的异常类型
void
0
0
输出方法的返回类型,参数类型,修饰符,以及方法的异常类型
void
0
0

七、通过反射调用方法

package com.study.test;

import static java.lang.System.*;

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

interface I1 {

}

interface I2 {

}

class aaa implements I1, I2 {

    public aaa() {
        out.println("aaa()");
    }

    public aaa(int i) {
        out.println("aaa(int i)");
    }

    protected aaa(int i, int j) {
        out.println("aaa(int i,String j)");
    }

    public void test() {
        out.println("void test()");
    }

    public void test1(int i) {
        out.println("void test1()");
    }

    void test2(int j, int k) {
        out.println("void test2()");
    }

}

public class ClassLoaderJZ {

    public static void main(String[] args) throws Exception {

        // getMethod()方法获得所有public的方法包括从Object继承的方法
        // for(Method m:aaa.class.getMethods()){
        // out.println(m);
        // };
        // getDeclaredMethods()方法获得所有在本类中自己声明的方法
        out.println("获得所有在本类中自己声明的方法");
        for (Method m : aaa.class.getDeclaredMethods()) {
            out.println(m);
        }
        // 注意:遍历出的构造函数是无序的
        out.println("构造函数");
        for (Constructor c : aaa.class.getDeclaredConstructors()) {
            out.println(c);
        }
        out.println("方法调用");
        aaa.class.getDeclaredMethods()[0].invoke(aaa.class.getDeclaredConstructors()[2].newInstance(), null);
        aaa.class.getDeclaredMethods()[1].invoke(aaa.class.getDeclaredConstructors()[1].newInstance(1), 1);
    }

}

输出结果:

获得所有在本类中自己声明的方法
public void com.study.test.aaa.test()
public void com.study.test.aaa.test1(int)
void com.study.test.aaa.test2(int,int)
构造函数
protected com.study.test.aaa(int,int)
public com.study.test.aaa(int)
public com.study.test.aaa()
方法调用
aaa()
void test()
aaa(int i)
void test1()

八、反射得到所有的字段

package com.study.test;

import static java.lang.System.out;

import java.io.IOException;
import java.lang.reflect.Field;

class aa {
    private int j = 2;
    public static int i = 1;

    void test1(int i) throws Exception, IOException {
        out.println("test");
    }

    public static int test2() {
        out.println("test1");
        return 1;
    }

}

public class ClassLoaderJZ {
    public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException,
            IllegalAccessException, InstantiationException {
        // 得到第一个字段内容
        Field f1 = aa.class.getDeclaredField("j");
        f1.setAccessible(true);
        out.println(f1.get(aa.class.newInstance()));
        // 得到第二个字段内容
        out.println(aa.class.getDeclaredField("i").get(null));

    }
}

输出结果:

2
1

posted @ 2017-10-06 22:26  小不点啊  阅读(390)  评论(0编辑  收藏  举报