• 反射和工厂设计模式(JAVA基础九)


    一、什么是类对象

    类的对象:基于某个类 new 出来的对象,也称为实例对象。

    类对象:类加载的产物,封装了一个类的所有信息(类名、父类、接口、属性、方法、构造方法) 。

    在这里插入图片描述

    注意:每个类加载到内存都会生成一个唯一的类对象

    二、获取类对象的方法

    • 通过类的对象,获取类对象。
    Student s = new Student();
    Class c = s.getClass();
    
    • 1
    • 2
    • 通过类名获取类对象。
    Class c = 类名.class;
    
    • 1
    • 通过静态方法获取类对象。
    Class c=Class.forName(“包名.类名”);
    
    • 1

    三、反射通用操作【重点】

    反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。

    3.1 常见方法

    方法名描述
    public String getName()获取类的完全名称
    public Package getPackage()获取包信息
    public Class getSuperclass()获取父类
    public Class[] getInterfaces()获取实现父接口
    public Field[] getFields()获取字段信息
    public Method[] getMethods()获取方法信息
    public Constructor[] getConstructors()获取构造方法
    public T newInstance()反射创建对象

    3.2 通用操作

    反射通用操作:使用反射机制获取类对象,并使用Class对象的方法获取表示类成员的各种对象(比如Constructor、Method、Field等),实现反射各种应用。

    案例演示:反射操作。

    Person类:

    public class Person implements Serializable,Cloneable{
    	//姓名
    	private String name;
    	//年龄
    	private int age;
    	
    	public Person() {
    		System.out.println("无参构造执行了...");
    	}
    	
    	public Person(String name, int age) {
    		super();
    		this.name = name;
    		this.age = age;
    		System.out.println("带参构造方法执行了...");
    	}
    
    	//吃
    	public void eat() {
    		System.out.println(name+"正在吃东西......");
    	}
    
    	@Override
    	public String toString() {
    		return "Person [name=" + name + ", age=" + age + "]";
    	}
    	//带参的方法
    	public void eat(String food) {
    		System.out.println(name+"开始吃...."+food);
    	}
    	
    	//私有的方法
    	private void privateMethod() {
    		System.out.println("这是一个私有方法");
    	}
    	
    	//静态方法
    	public static void staticMethod() {
    		System.out.println("这是一个静态方法");
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    TestPerson类:

    public class TestPerson {
    	public static void main(String[] args) throws Exception {
    		//调用测试以下方法
            //代码略
    	}
    	//获取类对象的三种方式
    	public static void getClazz() throws Exception {
    		//1使用对象获取类对象
    		Person zhangsan=new Person();
    		Class<?> class1=zhangsan.getClass();
    		System.out.println(class1.hashCode());
    		//2使用类名.class属性
    		Class<?> class2=Person.class;
    		System.out.println(class2.hashCode());
    		//3使用Class的静态方法[推荐使用]
    		Class<?> class3=Class.forName("com.qf.chap17_1.Person");
    		System.out.println(class3.hashCode());
    	}
    	
    	//1 使用反射获取类的名字、包名、父类、接口
    	public static void reflectOpe1() throws Exception {
    		//(1)获取类对象 Person
    		Class<?> class1=Class.forName("com.qf.chap17_1.Person");
    		//getName();
    		System.out.println(class1.getName());
    		//getPackage();
    		System.out.println(class1.getPackage().getName());
    		//getSuperClass();
    		System.out.println(class1.getSuperclass().getName());
    		//getInterfaces();
    		Class<?>[] classes=class1.getInterfaces();
    		System.out.println(Arrays.toString(classes));
    		
    		System.out.println(class1.getSimpleName());
    		System.out.println(class1.getTypeName());
    		
    	}
    	
    	//2使用反射获取类的构造方法,创建对象
    	public static void reflectOpe2() throws Exception{
    		//(1)获取类的类对象
    		Class<?> class1=Class.forName("com.qf.chap17_1.Person");
    		//(2)获取类的构造方法 Constructor
    		Constructor<?>[] cons=class1.getConstructors();
    		for (Constructor<?> con : cons) {
    			System.out.println(con.toString());
    		}
    		//(3)获取类中无参构造
    		Constructor<?> con=class1.getConstructor();
    		Person zhangsan=(Person)con.newInstance();
    		Person lisi=(Person)con.newInstance();
    		System.out.println(zhangsan.toString());
    		System.out.println(lisi.toString());
    		//简便方法:类对象.newInstance();
    		Person wangwu=(Person)class1.newInstance();
    		System.out.println(wangwu.toString());
    		//(4)获取类中带参构造方法
    		Constructor<?> con2=class1.getConstructor(String.class,int.class);
    		Person xiaoli=(Person)con2.newInstance("晓丽",20);
    		System.out.println(xiaoli.toString());
    	}
    	
    	//3使用反射获取类中的方法,并调用方法
    	public static void reflectOpe3() throws Exception{
    		//(1)获取类对象
    		Class<?> class1=Class.forName("com.qf.chap17_1.Person");
    		//(2)获取方法  Method对象
    		//2.1getMethods() 获取公开的方法,包括从父类继承的方法
    		//Method[] methods=class1.getMethods();
    		//2.2getDeclaredMethods() 获取类中的所有方法,包括私有、默认、保护的 、不包含继承的方法
    		Method[] methods=class1.getDeclaredMethods();
    		for (Method method : methods) {
    			System.out.println(method.toString());
    		}
    		//(3)获取单个方法
    		//3.1eat
    		Method eatMethod=class1.getMethod("eat");
    		//调用方法
    		//正常调用方法  Person zhangsan=new Person();  zhangsan.eat();
    		Person zhangsan=(Person)class1.newInstance();
    		eatMethod.invoke(zhangsan);//zhangsan.eat();
    		System.out.println("------------------");
    		//3.2toString
    		Method toStringMethod=class1.getMethod("toString");
    		Object result=toStringMethod.invoke(zhangsan);
    		System.out.println(result);
    		System.out.println("-------------------");
    		//3.3带参的eat 
    		Method eatMethod2=class1.getMethod("eat", String.class);
    		eatMethod2.invoke(zhangsan, "鸡腿");
    		
    		//3.4获取私有方法
    		Method privateMethod=class1.getDeclaredMethod("privateMethod");
    		//设置访问权限无效
    		privateMethod.setAccessible(true);
    		privateMethod.invoke(zhangsan);
    		
    		//3.4获取静态方法
    		Method staticMethod=class1.getMethod("staticMethod");
    		//正常调用 Person.staticMethod
    		staticMethod.invoke(null);
    		
    	}
    	
    	//4使用反射实现一个可以调用任何对象方法的通用方法
    	public static Object invokeAny(Object obj,String methodName,Class<?>[] types,Object...args) throws Exception {
    		//1获取类对象
    		Class<?> class1=obj.getClass();
    		//2获取方法
    		Method method=class1.getMethod(methodName, types);
    		//3调用
    		return method.invoke(obj, args);
    	}
    	
    	//5使用反射获取类中的属性
    	public static void reflectOpe4() throws Exception{
    		//(1)获取类对象
    		Class<?> class1=Class.forName("com.qf.chap17_1.Person");
    		//(2)获取属性(字段) 公开的字段,父类继承的字段
    		//Field[] fields=class1.getFields(); 
    		//getDeclaredFields()获取所有的属性,包括私有,默认 ,包含,
    		Field[] fields=class1.getDeclaredFields();
    		System.out.println(fields.length);
    		for (Field field : fields) {
    			System.out.println(field.toString());
    		}
    		//(3)获取name属性
    		Field namefield=class1.getDeclaredField("name");
    		namefield.setAccessible(true);
    		//(4)赋值  正常调用  Person zhangsan=new Person(); zhangsan.name="张三";
    		Person zhangsan=(Person)class1.newInstance();
    		namefield.set(zhangsan, "张三"); //zhangsan.name="张三";
    		//(5) 获取值
    		System.out.println(namefield.get(zhangsan));// zhangsan.name
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136

    四、设计模式【重点】

    4.1 概念

    • 一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
    • 可以简单理解为特定问题的固定解决方法。
    • 在Gof的《设计模式》书中描述了23 种设计模式。

    4.2 好处

    使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、重用性。

    4.3 工厂设计模式

    开发中有一个非常重要的原则“开闭原则”,对拓展开放、对修改关闭。

    工厂模式主要负责对象创建的问题。

    可通过反射进行工厂模式的设计,完成动态的对象创建。

    案例演示:

    IUsb接口:

    在这里插入图片描述

    package com.qfedu.pattern;
    
    //工厂模式:提供usb 接口
    
    public interface IUsb {
    
        void  service();
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    MouseImpl类:

    package com.qfedu.pattern;
    
    //鼠标
    
    public class MouseImpl implements  IUsb {
    
        @Override
        public void service() {
            System.out.println("鼠标业务逻辑.....");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    > FanImpl类:

    package com.qfedu.pattern;
    
    public class FanImpl implements  IUsb {
        @Override
        public void service() {
            System.out.println("风扇的业务逻辑......");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    KeyWordImpl类:

    package com.qfedu.pattern;
    
    public class KeyWordImpl implements  IUsb {
        @Override
        public void service() {
            System.out.println("键盘的业务逻辑.....");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    UsbFactory类:

    package com.qfedu.pattern;
    
    //usb对象的工厂:用来生产对象
    
    public class UsbFactory {
    
        //创建对象
        /**
         *
         * @param type  类的全限定路径名
         * @return
         */
        public IUsb  createUsb(String type) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
            //1获取class
            Class<?> usbClass = Class.forName(type);
            //2. 利用class 创建对象,并强转
            IUsb usb = (IUsb) usbClass.newInstance();
    
            return  usb;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    Test测试类:

    package com.qfedu.pattern;
    
    public class Test {
    
        public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
    
            //1 创建工厂对象
            UsbFactory usbFactory = new UsbFactory();
            //2.调用方法创建Iusb对象
            String type = "com.qfedu.pattern.MouseImpl";
            IUsb usb = usbFactory.createUsb(type);
    
            //3.多态情况下,:调用重写方法
            usb.service();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  • 相关阅读:
    微信小程序毕业设计-英语互助系统项目开发实战(附源码+论文)
    【Linux】传输层协议:TCP/UDP
    如何提高爬虫效率
    LATEX
    宝塔php站点设置伪静态规则 访问 a.com 时候跳转到 a.com/b.html
    动态规划与贪心算法
    pdf在线免费转word网站推荐,纯免费、不注册
    Midjourney基础参数详解
    文件操作--I/O
    1.4.14 实验14:ospf多区域
  • 原文地址:https://blog.csdn.net/LCHONSEONE/article/details/127699726