• 反射 扩展:代理,注解


    后续课程!!!!!!!

    maven

    SSH:struts+spring+hibernate

    微信公众号接口开发

    个人项目:物业微信公众号

    SSM:spring+springmvc+mybatis

    物业管理系统

    补充:

    shiro:权限认证

    redis

    git

    springboot

    springcloud

    反射

    一.概念

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

    对于任意一个对象,都能够访问它的任意一个方法和属性

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

    类中有什么信息 ,利用反射就能够获取,不过前提是知道这个类的名字(全称)

    想要解刨一个类,必须先获取类的字节码文件对象

    而解刨使用的就是Class类中的方法,所以先获取到每个字节码文件对应的Class类型的对象.

    Class一个类,封装了当前对象所对应的类的信息(属性,方法)

    在程序运行期间,一个类,只有一个Class对象产生

    二.获取Class类对象的三种方式

    1.对象名.getClass()

    2.通过类型.class

    3.Class.forName(包名.类名)

    案例

    1、Student类

    package com.po;
    
    public class Student {
        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;
        }
        
        
    }
    student
    package com.demo;
    
    import com.po.Student;
    
    public class Demo1 {
        public static void main(String[] args) throws ClassNotFoundException {
            //第一种
            Student s=new Student();
            Class c=s.getClass();
            System.out.println(c.getName());
            
            //第二种
            Class c2=Student.class;
            System.out.println(c2.getName());
            //第三种
            Class c3=Class.forName("com.po.Student");
            System.out.println(c3.getName());
            
            System.out.println(c2==c3);
        }
        
        
        
    }
    获取Class类对象的三种方式

    三.反射访问构造方法

    1、Student类

    public Student(){
            
        }
        public Student(String name,int age){
            this.name = name;
            this.age = age;
        }
        private Student(String name){
                this.name = name;
        }
    student类
    package com.demo;
    
    import java.lang.reflect.Constructor;
    
    import com.po.Student;
    
    public class Demo2 {
    
        public static void main(String[] args) throws Exception {
            Class c=Class.forName("com.po.Student");
            //获取所有的构造方法
            Constructor[] cons=c.getDeclaredConstructors();
            for (Constructor constructor : cons) {
                System.out.println(constructor);
            }
            //无参构造方法
            Constructor constructor=c.getConstructor();
            Student s=(Student)constructor.newInstance();
            System.out.println(s.getStuNo()+s.getStuName());
            
            //有参数的构造方法
            Constructor constructor2= c.getConstructor(int.class,String.class);
            Student s2=(Student)constructor2.newInstance(1,"张三");
            System.out.println(s2.getStuNo()+s2.getStuName());
            
        }
    
    }
    访问构造方法

     

    四.反射 访问公共属性

    package com.demo;
    
    import java.lang.reflect.Field;
    
    import com.po.Student;
    
    public class Demo3 {
        public static void main(String[] args) throws Exception {
            
            //获取Student的字节码文件
            Class c=Student.class;
            //获取所以公共的属性
            Field[] fields2=c.getDeclaredFields();
            for(Field filed:fields2){
                System.out.println(filed);
            }
            //根据类中的属性名称,获取特定的某个属性
            Field stuNo=c.getDeclaredField("stuNo");
            Field stuName=c.getDeclaredField("stuName");
            
            //为属性赋值
            //如果成员权限的属性石private,需要用下面的代码来解除私有权限的规则,否则抛异常
            Student s=(Student)c.newInstance();//通过反射创建Student对象,注意:学生类中必须有一个不带参的的构造方法
            stuNo.setAccessible(true);
            stuName.setAccessible(true);
            //为成员变量赋值,
            stuNo.set(s, 1);
            stuName.set(s, "张三");
            System.out.println(s.getStuNo()+s.getStuName());
        }
        
        
    
    }
    访问公共属性

    五.反射 访问成员方法

    1、Student类

    新增两个方法

    public void ceshi(){
            System.out.println("ceshi........");
        }
        
        public int add(int a,int b){
            return a+b;
        }
    student
    package com.demo;
    
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    import com.po.Student;
    
    public class Demo4 {
        public static void main(String[] args) throws Exception {
            Class c=Student.class;
            
            Method[] methods=c.getMethods();
            for (Method method : methods) {
                System.out.println(method);        
            }
            Method method=c.getMethod("ceshi");
            //执行方法
            Student s=(Student)c.newInstance();//反射创建对象
            Object result=method.invoke(s);//执行方法,此方法的所属对象
            System.out.println(result);
            
            System.out.println("--------------------------------");
            //执行有参数的方法     第一个参数:方法名称,后面的参数:方法参数的类型列表
            Method method2=c.getMethod("add", int.class,int.class);
            //第一个参数:方法所属的对象,后面的参数:方法的参数值列表,顺序和上面的类型顺序要一一对应
            Object result2=method2.invoke(s, 3,5);
            System.out.println(result2);
        }
    }
    访问成员方法

    六.设计模式-工厂模式

    23种

    工厂用来创建对象的,需要一个student对象,通过工厂创建一个student对象

    案例,动物工厂案例

    接口类

    package com.factory;
    
    public interface Animal {
        void eat();//
        
    }
    创建一个动物接口类
    package com.factory;
    
    public class AnimalFactory {
        public static Animal getInstance(String name) throws Exception{
    //        if("dog".equals(name)){
    //            return new Dog();
    //        }
    //        if("cat".equals(name)){
    //            return new Cat();
    //        }
            //利用反射创建动物对象
            Class c=Class.forName(name);
            Animal animal=(Animal)c.newInstance();
            
            return animal;
        }
    }
    利用反射创建动物工厂对象
    package com.factory;
    
    public class Cat implements Animal{
    
        @Override
        public void eat() {
            System.out.println("cat.. eat");
            
        }
        
    }
    实现动接口 cat
    package com.factory;
    
    public class Dog implements Animal{
    
        @Override
        public void eat() {
            System.out.println("dog...eat");
            
        }
        
    }
    实现动物接口dog
    package com.factory;
    
    public class cehsi {
    
        public static void main(String[] args) throws Exception {
    //        Animal animal=AnimalFactory.getInstance("cat");
    //        animal.eat();
            Animal animal=AnimalFactory.getInstance("com.factory.Cat");
            animal.eat();
        }
    
    }
    测试类

    此时的效果,就是我们在测试类中,传入”cat”时,Animal是Cat类型对象,传入“dog”时,Animal是Dog类型对象;

    当我们的Animal接口有其他的动物实现类时,我们就需要在AnimalFactory工厂类的getInstance()方法中新增其他动物对象的分支语句及创建对象;显然不合理,此时我们可以在工厂类中使用反射的方式创建对象,这样不管Animal有多少实现类,只需要传入相应类型,即可创建对象

    6、优化

    AnimalFactory类修改

    //根据传递的名称,创建不同的动物对象
        public static Animal getInstance(String name) throws Exception{
            /*if("dog".equals(name)){
                return new Dog();
            }
            if("cat".equals(name)){
                return new Cat();
            }*/
            
            //利用反射,创建动物对象
            Class c = Class.forName(name);
            Animal animal =  (Animal) c.newInstance();
            
            return animal;
        }
    AnimalFactory类修改

    测试类

    public static void main(String[] args) throws Exception {
            //Animal animal = AnimalFactory.getInstance("cat");
            //animal.eat();
            
                //传入类的全称
            Animal animal = AnimalFactory.getInstance("com.factory.Cat");
            animal.eat();
        }
    测试类

    最终我们的效果,就是只需修改传入的参数,就能创建不同类型的Animal对象

    补充:其实这里的测试类中传入的类全称,我们每次还是需要更改源代码,才能生效,最好的方式可以把类全称配置到特定的配置文件中,如xml、properties等文件,我们代码中只需读取配置文件,即可灵活的控制对象的产生

    七、结论

    重点掌握反射的概念以及操作类的属性和方法;

    通过反射,只需要获取到类的Class字节码类型对象,我们就能很好的操作类的对象创建、属性的赋值、方法的调用;

    反射要导的包

    import java.lang.reflect.

  • 相关阅读:
    设计模式 --> (3)策略模式
    设计模式 --> (2)单例模式
    设计模式 --> (1)工厂模式
    Algorithm --> 十大排序算法
    Algorithm --> 求阶乘末尾0的个数
    网络通信 --> epoll用法
    数据库 --> sqlite3之api使用
    网络通信 --> select()用法
    网络通信 --> TCP三次握手和四次挥手
    『转载』周立功:专注的力量成就梦想
  • 原文地址:https://www.cnblogs.com/faded8679/p/10722651.html
Copyright © 2020-2023  润新知