反射

 

JAVA 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方

法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以

及动态调用对象的方法的功能称为 java 语言的反射机制。

public class Simple {
    public static void main(String[] args) {
        Simple s = new Simple();

//包名.类名
        System.out.println(s.getClass().getName());
    }
}

Java 反射机制,可以实现以下功能:

①在运行时判断任意一个对象所属的类;

②在运行时构造任意一个类的对象;

③在运行时判断任意一个类所具有的成员变量和方法;

④在运行时调用任意一个对象的方法;

⑤生成动态代理。

一、获取源头 Class

打开权限:

add.setAccessible(true);

所有类的对象其实都是 Class 的实例。这个 Class 实例可以理解为类的模子,就是包含

了类的结构信息,类似于图纸。

创建对象方法:  序列化:实现 serializable 接口,

反序列化

克隆:实现 cloneable 接口,重写 clone()方法,修改权限为 public

New

反射

获取类的 class 对象,有三种方式可以实现:

Class.forName(”包名.类名”)//一般尽量采用该形式

②类.class

③对象.getClass()

public class Source {
    public static void main(String[] args) {
        //第一种方式 对象.getClass
        Source s = new Source();
        Class<?> c1 = s.getClass();
        //第二种方式 类.class
        Class<?> c2 = Source.class;
        //第三种方式(推荐使用) Class.forName(”包名.类名”)
        Class<?> c3 = null;
        try {
            c3 = Class.forName(“com.jssh.reflection.Source”);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println(c1.getName());
        System.out.println(c2.getName());
        System.out.println(c3.getName());
    }
}

 

二、 构造器

根据 Class 对象,我们可以获得构造器,为实例化对象做准备。调用以下 api 即可

 

 

public class GetConstructor {
    public static void main(String[] args) {
        try {
            //获取class对象
            Class<?> clz = Class.forName(“com.jssh.reflection.User”);
            //1.获取所有public权限的构造器
            Constructor<?>[] con = clz.getConstructors();
            //注意查看构造器顺序
            for (Constructor<?> c : con){
                System.out.println(c);
            }
            //2.获取所有构造器
            con= clz.getDeclaredConstructors();
            for (Constructor<?> c:con ){
                System.out.println(c);
            }
            //3.获取指定的构造器(放入具体的类型)
            Constructor<?> c = clz.getConstructor(String.class);
            System.out.println(c);
            //4.非public权限的
            c = clz.getDeclaredConstructor(String.class,Integer.class);
            System.out.println(c);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}

三、 实例化对象

之前我们讲解过创建对象的方式,new 、克隆、反序列化,再加一种,根据 Class

象,使用 newInstance() 或者构造器实例化对象。

 

public class UserImpl {
    public static void main(String[] args) {
        Class<?> clz =null;
        try {
            //获取源头
            clz =Class.forName(“com.jssh.reflection.User”);
            //第一种:通过newInstance()创建对象
            User user = (User) clz.newInstance();
            user.setName(“xiaoming”);
            user.setAge(18);
            System.out.println(user.getName()+“——–>”+user.getAge());
            //第二种:通过getDeclaredConstructors()创建对象,取得全部构造函数(注意顺序)
            Constructor<?>[] cons = clz.getDeclaredConstructors();
            for (Constructor<?> con:cons){
                System.out.println(con);
            }
            //注意观察上面的输出结果,在实例化,否则参数容易出错
            User u1 = (User) cons[0].newInstance(“xxx”,18);
            User u2 = (User) cons[1].newInstance(“xxx”);
            User u3 = (User) cons[2].newInstance();
            System.out.println(u1.getName()+“——->”+u1.getAge());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

 

注意:newInstance()是调用空构造,如果空构造不存在,会出现异常。由此可知,使

用其他构造器创建对象比较麻烦,使用空构造非常简单。确保空构造存在。

四、 接口与父类

通过 api 获取接口与父类

 

五、 修饰符

获取修饰符,使用 Modifier 即可

 

六、 属性

获取所有属性(包括父类或接口) ,使用 Field 即可操作

public class GetField {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> clz = Class.forName(“com.jssh.reflection.User”);
        //获取类的全部属性
        Field[] fields = clz.getDeclaredFields();
        for (int i=0;i<fields.length;i++){
            //1.获取权限修饰符
            int mo = fields[i].getModifiers();
            String s = Modifier.toString(mo);
            //2.属性类型
            Class<?> type = fields[i].getType();
            //3.名字
            String name = fields[i].getName();
            System.out.println(s+“===”+type+“===”+name);
        }
        //公开的属性:包括接口或者父类属性
        Field[] fields1 = clz.getFields();
        for (int i =0;i<fields1.length;i++){
            System.out.println(fields1[i]);
        }
    }
}

七、 方法

获取所有方法(包括父类或接口),使用 Method 即可。

 

 

八、 数组

操作数组需要借助 Array

public class ArrayTest {
    public static void main(String[] args) {
        //1.创建数组
        Object o = Array.newInstance(int.class, 5);
        //2.获取大小
        if (o.getClass().isArray()){//3、判断是否为数组
            System.out.println(Array.getLength(o));
            //4.设置值
            Array.set(o,0,100);
            //5.获取值
            System.out.println(Array.get(o,0));
        }
    }
}

 

九、 类加载器

java 中有三种类类加载器:

Bootstrap ClassLoader 此加载器采用 c++编写,一般开发中很少见。

Extension ClassLoader 用来进行扩展类的加载,一般对应的是 jre\lib\ext 目录中的类

AppClassLoader 加载 classpath 指定的类,是最常用的加载器。同时也是 java 中默认

的加载器。 了解即可。

在程序执行中 JVM 通过装载,链接,初始化这 3 个步骤完成。

十、 反射相关操作( 重点)

1、操作属性

//1、获取Class对象

Class<?> clz=Class.forName(“com.shsxt.ref.simple.User”);

//2、获取对象

User u=(User)clz.newInstance();

//3、设置属性

Field field=clz.getDeclaredField(“uname”);

field.setAccessible(true);//打开权限

field.set(u, “0523”);

//4、获取此属性

System.out.println(field.get(u));

 

 

2 、调用方法

调用方法,都是直接对象.方法([实参]);反射之后,动态调用方法需要使用 invoke 即可。

 

 

1)、方法调用

//1、获取Class对象

Class<?> clz=Class.forName(“com.shsxt.ref.simple.User”);

//2、获取对象

User u=(User)clz.newInstance();

//3、获取方法

Method m =clz.getMethod(“coding”, String.class,String.class);

//4、成员方法的调用

m.invoke(u, “反射“,”多个参数“);

//若是静态方法,传递null即可 因为静态方法属性类,不属于对象

m=clz.getMethod(“testStatic”,int.class);

m.invoke(null, 100);//与对象无关

2)、操作 setter getter 访问器

3 、利用反射编写简单工厂设计模式

利用反射+配置文件可以实现简单工厂模式。

版权声明:本文为mr-sun原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/mr-sun/p/8891421.html