(11)Java的反射机制(实例)

 

目录

1.通过一个对象获得完整的包名和类名

2.实例化Class类对象

3.通过Class实例化其他类的对象

4.通过Class调用其他类中的构造函数 (也可以通过这种方式用Class创建其他类的对象)

5.返回一个类实现的接口

6.取得其他类中的父类

7.获得其他类中的全部构造函数

8.取得其他类的全部属性,将这些整理在一起,也就是通过class取得一个类的全部框架

9.通过反射调用其他类中的方法

10.调用其他类的set和get方法

11.通过反射操作属性

12.通过反射取得并修改数组的信息

13.通过反射修改数组大小

14.动态代理

(1)获得类加载器

(2)想要完成动态代理,首先需要定义一个InvocationHandler接口的子类,以完成代理的具体操作。

15.IoC原理-Spring中的IoC的实现原理=工厂模式+反射

(1)不用反射机制时的工厂模式例子:

(2)利用反射机制的工厂模式

(3)使用反射机制并结合属性文件的工厂模式(即IoC)


1.通过一个对象获得完整的包名和类名

对象名.getClass().getName();
package com.review06.reflect;

public class Demo01 {
    public static void main(String[] args) {
        Demo01 demo01 = new Demo01();
        System.out.println(demo01.getClass().getName());//打印结果:com.review06.reflect.Demo01
    }
}

 

2.实例化Class类对象

package com.review06.reflect;

public class Demo02 {
    public static void main(String[] args) {
        Class<?> c1 = null;
        Class<?> c2 = null;
        Class<?> c3 = null;

        try {
            c1 = Class.forName("com.review06.reflect.Demo02"); //推荐
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        c2 = new Demo02().getClass();
        c3 = Demo02.class;

        System.out.println("类名称:"+c1.getName());
        System.out.println("类名称:"+c2.getName());
        System.out.println("类名称:"+c3.getName());
        //运行结果:
        //类名称:com.review06.reflect.Demo02
        //类名称:com.review06.reflect.Demo02
        //类名称:com.review06.reflect.Demo02
    }
}

 

3.通过Class实例化其他类的对象

package com.review06.reflect;

class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "[" + this.name + " " + age +"]";
    }
}

public class TestPerson {
    public static void main(String[] args) {
        Class<?> demo = null;
        try {//idea的try/catch快捷键:先选中要try/catch的,然后Ctrl+Alt+t
            demo = Class.forName("com.review06.reflect.Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Person person = null;

        try {
            person = (Person)demo.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        person.setName("Green");
        person.setAge(80);
        System.out.println(person);  //打印结果:  [Green 80]
    }
}

当我们把Person中的默认的无参构造函数取消的时候,自己定义只定义一个有参数的构造函数之后,会出现错误,比如定义如下的构造函数:

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }


所以以后在编写使用Class实例化其他类的对象的时候,一定要自己定义无参的构造函数(防止无参构造函数被覆盖)。否则会出现以上错误!

 

 

4.通过Class调用其他类中的构造函数 (也可以通过这种方式用Class创建其他类的对象)

package com.review06.reflect;

import java.lang.reflect.Constructor;

class Men {
    private String name;
    private int age;

    public Men() {

    }
    public Men(String name) {
        this.name = name;
    }
    public Men(int age) {
        this.age = age;
    }

    public Men(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "["+ this.name + " "+ this.age + "]";
    }
}

class TestMen {
    public static void main(String[] args) {
        Class<?> demo = null;
        try {
            demo = Class.forName("com.review06.reflect.Men");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Men men1 = null;
        Men men2 = null;
        Men men3 = null;
        Men men4 = null;
        //取得全部的构造函数
        Constructor<?> cons[] = demo.getConstructors();
        try {
            men1 = (Men) cons[0].newInstance();
            men2 = (Men) cons[1].newInstance("Tom");
            men3 = (Men) cons[2].newInstance(15);
            men4 = (Men) cons[3].newInstance("Mike",62);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(men1+"\t"+men2+"\t"+men3+"\t"+men4);
    }
}

 

 

5.返回一个类实现的接口

package com.review06.reflect;

interface Chinese {
    public static final String name="Rollen";
    public static int age = 20;
    public void sayChinese();
    public void sayHello(String name,int age);
}

interface A {}

class CPerson implements Chinese,A {
    private String sex;
    public CPerson() {
    }
    public CPerson(String sex) {
        this.sex = sex;
    }

    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public void sayChinese() {
        System.out.println("hello,China");
    }

    @Override
    public void sayHello(String name, int age) {
        System.out.println(name +" "+ age);
    }
}

public class TestChinese {
    public static void main(String[] args) {
        Class<?> demo = null;
        try {
            demo = Class.forName("com.review06.reflect.CPerson");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //保存所有的接口
        Class<?> intes[] = demo.getInterfaces();
        for(int i=0; i<intes.length; i++) {
            System.out.println("实现的接口:"+intes[i].getName());//打印结果:实现的接口:com.review06.reflect.Chinese
        }
        //打印结果:
        //实现的接口:com.review06.reflect.Chinese
        //实现的接口:com.review06.reflect.A
    }
}

 

(下面例子中,上面写过的Person类、Men类、CPerson类都省略不写了)

 

6.取得其他类中的父类

package com.review06.reflect;

public class TestSuper {
    public static void main(String[] args) {
        Class<?> demo = null;
        try {
            demo = Class.forName("com.review06.reflect.Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //取得父类
        Class<?> temp = demo.getSuperclass();
        System.out.println("继承的父类为:"+temp.getName());
        //打印结果:  继承的父类为:java.lang.Object
    }
}

7.获得其他类中的全部构造函数

package com.review06.reflect;

import java.lang.reflect.Constructor;

public class TestConstructor {
    public static void main(String[] args) {
        Class<?> demo = null;
        try {
            demo = Class.forName("com.review06.reflect.Men");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Constructor<?> cons[] = demo.getConstructors();
        for(int i=0; i<cons.length; i++) {
            System.out.println("构造方法:"+cons[i]);
        }
    }
}

打印结果:

 

 

8.取得其他类的全部属性,将这些整理在一起,也就是通过class取得一个类的全部框架

package com.review06.reflect;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class TestAttribute {
    public static void main(String[] args) {
        Class<?> demo = null;
        try {
            demo = Class.forName("com.review06.reflect.CPerson");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println("=======本类属性=======");
        Field[] field = demo.getDeclaredFields();
        for(int i=0; i<field.length; i++) {
            //权限修饰符
            int modifier = field[i].getModifiers();
            String priv = Modifier.toString(modifier);
            //属性类型
            Class<?> type = field[i].getType();
            System.out.println(priv+" "+type.getName()+" "+field[i].getName()+";");
        }

        System.out.println("\n=======实现的接口或者父类的属性=======");
        //取得实现的接口或者父类的属性
        Field[] field1 = demo.getFields();
        for (int j=0; j<field1.length; j++) {
            //权限修饰符
            int modifier = field1[j].getModifiers();
            String priv = Modifier.toString(modifier);
            //属性类型
            Class<?> type = field1[j].getType();
            System.out.println(priv+" "+type.getName()+" "+field1[j].getName()+";");
        }
    }
}

 

 

 

9.通过反射调用其他类中的方法

package com.review06.reflect;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestMethod1 {
    public static void main(String[] args) {
        Class<?> demo = null;
        try {
            demo = Class.forName("com.review06.reflect.CPerson");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        try {
            //调用CPerson类中的sayChinese方法
            Method method = demo.getMethod("sayChinese");
            method.invoke(demo.newInstance());
            //调用CPerson的sayHello方法
            method = demo.getMethod("sayHello",String.class, int.class);
            method.invoke(demo.newInstance(),"Tom",45);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }
}

 

10.调用其他类的set和get方法

package com.review06.reflect;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class SetterGetter {
    public static void main(String args[]) {
        Class<?> demo = null;
        Object obj = null;
        try {
            demo = Class.forName("com.review06.reflect.Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        try {
            obj = demo.newInstance();
        } catch (InstantiationException e) {
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        setter(obj,"Name","张三", String.class);
        getter(obj,"Name");

    }

    /**
     * @param obj 操作的对象
     * @param attr 操作的属性
     */
    public static void getter(Object obj, String attr) {
        try {
            Method method = obj.getClass().getMethod("get"+attr);
            System.out.println(method.invoke(obj));
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param obj 操作对象
     * @param attr 操作的属性
     * @param value 设置的值
     * @param type 参数的值
     */
    public static void setter(Object obj, String attr, Object value, Class<?> type) {
        try {
            Method method = obj.getClass().getMethod("set"+attr, type);
            method.invoke(obj,value);
        } catch (NoSuchMethodException e) {
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

 

11.通过反射操作属性

package com.review06.reflect;

import java.lang.reflect.Field;

public class TestSetAttr {
    public static void main(String[] args) throws Exception {
        Class<?> demo = null;
        Object obj = null;

        demo = Class.forName("com.review06.reflect.Person");
        obj = demo.newInstance();

        Field field = demo.getDeclaredField("name");
        field.setAccessible(true);
        field.set(obj,"李四");
        System.out.println(field.get(obj));
    }
}

 

 

12.通过反射取得并修改数组的信息

package com.review06.reflect;

import java.lang.reflect.Array;

public class TestAlertArrayInfo {
    public static void main(String[] args) {
        int[] temp = {1,5,7,45,4};
        Class<?> demo = temp.getClass().getComponentType();
        System.out.println("数组类型:"+ demo.getName());
        System.out.println("数组长度:"+ Array.getLength(temp));
        System.out.println("数组的第一个元素:"+Array.get(temp,0));
        Array.set(temp,0,100);
        System.out.println("修改后数组第一个元素为:"+Array.get(temp, 0));
    }
}

 

 

13.通过反射修改数组大小

package com.review06.reflect;

import java.lang.reflect.Array;

public class TestAlertArraySize {
    public static void main(String[] args) {
        int[] temp = {1,2,4,5,1,3,15,13};
        int[] newTemp = (int[]) arrayInc(temp,15);
        print(newTemp);
        System.out.println("\n===========");
        String [] arr = {"a","b","c"};
        String [] str1 = (String[])arrayInc(arr,8);
        print(str1);
    }

    /**
     * 修改数组大小
     * @param obj 修改前的数组
     * @param len 新数组长度
     * @return 新的数组
     */
    public static Object arrayInc(Object obj, int len) {
        Class<?> arr = obj.getClass().getComponentType();
        Object newArr = Array.newInstance(arr,len);
        int co = Array.getLength(obj);
        System.arraycopy(obj,0,newArr,0,co);
        return newArr;
    }

    /**
     * 打印
     */
    public static void print(Object obj) {
        Class<?> c = obj.getClass();
        if(!c.isArray()) {
            return;
        }
        System.out.println("数组长度为:"+Array.getLength(obj));
        for(int i=0; i<Array.getLength(obj); i++) {
            System.out.print(Array.get(obj,i) + " ");
        }
    }
}

 

 

14.动态代理

(1)获得类加载器

package com.review06.reflect;

public class GetClassLoader {
    public static void main(String[] args) {
        Person person = new Person();
        System.out.println("Person的类加载器——"+
                person.getClass().getClassLoader().getClass().getName());
        //打印: Person的类加载器——sun.misc.Launcher$AppClassLoader
    }
}

(2)想要完成动态代理,首先需要定义一个InvocationHandler接口的子类,以完成代理的具体操作。

package com.review06.reflect;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DynamicAgency {
    public static void main(String[] args) {
        MyInvocationHandler demo = new MyInvocationHandler();
        Subject sub = (Subject) demo.bind(new RealSubject());
        String info = sub.say("Chili",21);
        System.out.println(info); //打印:Chili 21
    }
}
//定义项目接口
interface Subject {
    public String say(String name,int age);
}

//定义真实项目
class RealSubject implements Subject {
    @Override
    public String say(String name, int age) {
        return name+" "+age;
    }
}

class MyInvocationHandler implements InvocationHandler {
    private Object obj = null;

    public Object bind(Object obj) {
        this.obj = obj;
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
                obj.getClass().getInterfaces(),this::invoke);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object temp = method.invoke(this.obj,args);
        return temp;
    }
}

 

15.IoC原理-Spring中的IoC的实现原理=工厂模式+反射

(1)不用反射机制时的工厂模式例子:

package com.review06.reflect;

interface Phone {
    public abstract void call();
}
class Huawei implements Phone {
    @Override
    public void call() {
        System.out.println("Huawei");
    }
}
class Mi implements Phone {
    @Override
    public void call() {
        System.out.println("Mi");
    }
}

//构造工厂类,以后在添加其他实例的时候只需要修改工厂类就OK了
class PhoneFactory {
    public static Phone getInstance(String phoneName) {
        Phone phone = null;
        if("Huawei".equals(phoneName)) {
            phone = new Huawei();
        }
        if("Mi".equals(phoneName)) {
            phone = new Mi();
        }
        return phone;
    }
}

public class TestFactory {
    public static void main(String[] args) {
        Phone phone = PhoneFactory.getInstance("Mi");
        phone.call();  //打印:Mi
    }
}

上述代码中,若再添加一个Phone的子类,就需要修改工厂类了。如果我们添加太多的子类,改的就会很多。

 

 

 

(2)利用反射机制的工厂模式

package com.review06.reflect;

import com.sun.xml.internal.ws.client.sei.ResponseBuilder;

interface RPhone {
    public abstract void call();
}
class RHuawei implements RPhone {
    @Override
    public void call() {
        System.out.println("Huawei");
    }
}
class RMi implements RPhone {
    @Override
    public void call() {
        System.out.println("Mi");
    }
}
class RPhoneFactory {
    public static RPhone getInstance(String ClassName) {
        RPhone rphone = null;
        try {
            rphone = (RPhone) Class.forName(ClassName).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return rphone;
    }
}


public class TestReflectFactory {
    public static void main(String[] args) {
        RPhone rphone = RPhoneFactory.getInstance("com.review06.reflect.RMi");
        if(rphone != null) {
            rphone.call();
        }
    }
}

现在就算我们添加任意多个子类的时候,工厂类就不需要修改。

  使用反射机制的工厂模式可以通过反射取得接口的实例,但是需要传入完整的包和类名。而且用户也无法知道一个接口有多少个可以使用的子类,所以我们通过属性文件的形式配置所需要的子类。

 

(3)使用反射机制并结合属性文件的工厂模式(即IoC)

将上面的代码稍作修改(添加一个操作属性文件的类,修改main方法)

package com.review06.reflect;

import java.io.*;
import java.util.Properties;

interface RPhone {
    public abstract void call();
}
class RHuawei implements RPhone {
    @Override
    public void call() {
        System.out.println("Huawei");
    }
}
class RMi implements RPhone {
    @Override
    public void call() {
        System.out.println("Mi");
    }
}

//操作属性文件类
class OperationPropFile {
    public static Properties getPro() throws FileNotFoundException, IOException{
        Properties pro = new Properties();
        File file = new File("rphone.properties");
        if(file.exists()) {
            pro.load(new FileInputStream(file));
        }else {
            pro.setProperty("huawei","com.review06.reflect.RHuawei");
            pro.setProperty("mi","com.review06.reflect.RMi");
            pro.store(new FileOutputStream(file),"RPhone Class");
        }
        return pro;
    }

}

class RPhoneFactory {
    public static RPhone getInstance(String ClassName) {
        RPhone rphone = null;
        try {
            rphone = (RPhone) Class.forName(ClassName).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return rphone;
    }
}


public class TestReflectFactory {
    public static void main(String[] args) throws FileNotFoundException,IOException {
        Properties pro = OperationPropFile.getPro();
        RPhone rphone = RPhoneFactory.getInstance(pro.getProperty("huawei"));
        if(rphone != null) {
            rphone.call(); //打印: Huawei
        }
    }
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值