Java基础整理(二十二)

反射机制(下)

传送门:反射机制(上)

8. 反射属性Field

(1)常用方法

Student类

public class Student {

    //4个Field,分别采用了不同的访问控制权限修饰符
    private String name;
    protected int id;
    boolean sex;
    public int no;

}

:其实一个属性就代表一个Field,即private String name是一个Field,boolean sex是一个Field

Test类

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

        //获取整个类
        Class studentClass = Class.forName("com.study.www.field.Student");

        String className = studentClass.getName();
        //com.study.www.field.Student
        System.out.println(className);

        String classSimpleName = studentClass.getSimpleName();
        //Student
        System.out.println(classSimpleName);

        //获取类中所有public修饰的Field
        Field[] fields = studentClass.getFields();
        System.out.println(fields.length); //1
        //取出这个Field
        Field f = fields[0];
        System.out.println(f.getName()); //no

        //获取类中所有Field
        Field[] fieldsAll = studentClass.getDeclaredFields();
        System.out.println(fieldsAll.length); //4
        for(Field field : fieldsAll){

            //获取属性的修饰符列表
            //返回的修饰符是一个数字,每个数字是修饰符的代号,多个修饰符也会有一个代号
            int i = field.getModifiers(); 
            String modifierString = Modifier.toString(i);
            //private protected     public
            System.out.println(modifierString);
            
            //获取属性的类型
            Class fieldType =field.getType();
            System.out.println(fieldType.getName());//java.lang.String int boolean int
            System.out.println(fieldType.getSimpleName()); //String int boolean int
            
            //获取属性的名字
            System.out.println(field.getName());//name id sex no
        }
    }
}

(2)反编译Field实例
public class Test {
    public static void main(String[] args) throws Exception {

        StringBuilder sb = new StringBuilder();

        Class studentClass = Class.forName("com.study.www.field.Student");
        sb.append(Modifier.toString(studentClass.getModifiers()) + " class " + studentClass.getSimpleName() + "{\n");
        Field[] fields = studentClass.getDeclaredFields();
        for(Field field : fields){
            String modifierString = Modifier.toString(field.getModifiers());
            sb.append("\t" + modifierString + " ");
            sb.append(field.getType().getSimpleName()+" ");
            sb.append(field.getName()+";\n");
        }
        sb.append("}");
        System.out.println(sb);

    }
}

输出结果:在这里插入图片描述


(3)通过反射机制访问对象属性
  • 在不使用反射机制之前,我们访问对象属性的方式

    public class Test {
        public static void main(String[] args) throws Exception {
    
            Student stu = new Student();
            stu.no = 1111;
            System.out.println(stu.no);
    
        }
    }
    
  • 通过反射机制访问对象属性

    public class Test {
        public static void main(String[] args) throws Exception {
    
            Class studentClass = Class.forName("com.study.www.field.Student");
            //obj就是Student对象,底层调用无参构造
            Object obj = studentClass.newInstance();
    
            //获取属性no
            Field noField = studentClass.getDeclaredField("no");
            //给obj对象(Student对象)的属性no赋值,赋值1111
            noField.set(obj,1111);
            //获取obj对象的属性no的值
            System.out.println(noField.get(obj));
            
        }
    }
    

    如果是私有属性怎么办?通过反射机制可以访问到吗?

    可以,需要调用setAccessible(true)方法

    public class Test {
        public static void main(String[] args) throws Exception {
    
            Class studentClass = Class.forName("com.study.www.field.Student");
            //obj就是Student对象,底层调用无参构造
            Object obj = studentClass.newInstance();
    
            //获取属性name
            Field nameField = studentClass.getDeclaredField("name");
            //打破封装,在外部也可以访问私有属性,不安全
            nameField.setAccessible(true);
            nameField.set(obj,"lisi");
            System.out.println(nameField.get(obj));
    
        }
    }
    

9. 反射方法Method

(1)常用方法
public class Test {
    public static void main(String[] args) throws Exception {

        //获取类
        Class userServiceClass = Class.forName("com.study.www.field.UserService");

        //获取所有的Method(包括私有的)
        Method[] methods = userServiceClass.getDeclaredMethods();
        System.out.println(methods.length);//2
        for(Method method : methods){
            //获取修饰符列表
            System.out.println(Modifier.toString(method.getModifiers())); //public
            //获取方法的返回类型
            System.out.println(method.getReturnType().getSimpleName());//void boolean
            //获取方法的名字
            System.out.println(method.getName());//logout login
            //方法的参数修饰符列表(一个方法可能有多个参数)
            Class[] parameterTypes= method.getParameterTypes();
            for(Class parameterType : parameterTypes){
                System.out.println(parameterType.getSimpleName()); //String String
            }
        }
    }
}

(2)反编译Method
public class Test {
    public static void main(String[] args) throws Exception {

        StringBuilder sb = new StringBuilder();
        Class userService = Class.forName("com.study.www.field.UserService");
        sb.append(Modifier.toString(userService.getModifiers())+" class "+userService.getSimpleName()+" {\n");

        Method[] methods = userService.getDeclaredMethods();
        for(Method method : methods){
            sb.append("\t"+Modifier.toString(method.getModifiers())+" ");
            sb.append(method.getReturnType().getSimpleName()+" ");
            sb.append(method.getName()+"(");
            Class[] parameterMethod = method.getParameterTypes();
            for(Class parameterClass : parameterMethod){
                sb.append(parameterClass.getSimpleName()+", ");
            }
            //删除末尾多余的符号
            if(", ".equals(sb.substring(sb.length()-2,sb.length()))){
                sb.delete(sb.length()-2,sb.length());
            }
            sb.append("){}\n");
        }
        sb.append("}");
        System.out.println(sb);
    }
}

输出结果:在这里插入图片描述


(3)通过反射机制调用方法
  • 不采用反射机制时

    public class Test {
        public static void main(String[] args) throws Exception {
    
            UserService userService = new UserService();
            System.out.println(userService.login("admin","123"));
            userService.logout();
    
        }
    }
    
  • 采用反射机制时

    public class Test {
        public static void main(String[] args) throws Exception {
    
            Class userServiceClass = Class.forName("com.study.www.field.UserService");
            Object obj = userServiceClass.newInstance();
    
            //获取Method
            //参数列表:方法的名字,两个方法参数的Class(如果int直接int.class 参数类型.class)
            Method loginMethod = userServiceClass.getMethod("login",String.class,String.class);
            //loginMethod是获取的方法,obj是创建的对象
            //"admin","123"是传进方法的两个实参
            //retValue是方法的返回值
            Object retValue = loginMethod.invoke(obj,"admin","123");
            System.out.println(retValue); //true
    
        }
    }
    
  • 总结

    反射机制,让代码具有通用性,可变化的内容都是写到配置文件当中,将来修改配置文件之后,创建的对象就不一样了,调用的方法也不同了,但是Java代码不需要任何的改动


10. 反射构造器Constructor

Student类

public class Student {
    
    private String name;
    private int id;
    private int no;

    public Student() {
    }

    public Student(String name) {
        this.name = name;
    }

    public Student(String name, int id) {
        this.name = name;
        this.id = id;
    }

    public Student(String name, int id, int no) {
        this.name = name;
        this.id = id;
        this.no = no;
    }
}
(1)反编译Constructor
public class Test {
    public static void main(String[] args) throws Exception {

        StringBuilder sb = new StringBuilder();
        Class studentClass = Class.forName("com.study.www.field.Student");
        sb.append(Modifier.toString(studentClass.getModifiers())+ " class "+studentClass.getSimpleName()+"{\n");

        Constructor[] constructors = studentClass.getDeclaredConstructors();
        for(Constructor constructor : constructors){
            //构造器没有返回类型,且命名都和类一样
            sb.append("\t" + Modifier.toString(constructor.getModifiers())+ " "+ studentClass.getSimpleName()+"(");
            Class[] parameterTypes = constructor.getParameterTypes();
            for(Class c : parameterTypes){
                sb.append(c.getSimpleName()+",");
            }
            if(parameterTypes.length>0)
                sb.deleteCharAt(sb.length()-1);
            sb.append("){}\n");
        }
        sb.append("}");
        System.out.println(sb);

    }
}

运行结果:在这里插入图片描述


(2)通过反射机制调用构造器
  • 不使用反射机制

    public class Test {
        public static void main(String[] args) throws Exception {
    
            //不使用反射机制调用构造器创建对象
            Student student = new Student();
            Student student1 = new Student("lisi",111);
            Student student2 = new Student("zhangsan",222,2);
        }
    }
    
  • 使用反射机制

    public class Test {
        public static void main(String[] args) throws Exception {
    
            //不使用反射机制调用构造器创建对象
            Student student = new Student();
            Student student1 = new Student("lisi",111);
            Student student2 = new Student("zhangsan",222,2);
    
    
            Class studentClass = Class.forName("com.study.www.field.Student");
    
            //调用无参数构造方法
            Object obj = studentClass.newInstance();
            System.out.println(obj);
    
            //调用无参数构造方法的第二种方式
            Constructor c1 = studentClass.getDeclaredConstructor();
            Object obj1 = c1.newInstance();
            System.out.println(obj1);
    
    
            //调用有参数的构造方法
            //先获取这个有参数的构造方法
            Constructor c = studentClass.getDeclaredConstructor(String.class,int.class,int.class);
            //调用构造方法new对象
            Object obj2 = c.newInstance("wangwu",333,3);
    
            System.out.println(obj2);
        }
    }
    

    运行结果:在这里插入图片描述


11. 获取父类以及实现的接口

  • 获取一个类的父类:getSuperclass()

    public class Test {
        public static void main(String[] args) throws Exception {
    
            Class stringClass = Class.forName("java.lang.String");
    
            //获取String父类
            Class superClass = stringClass.getSuperclass();
            //java.lang.Object
            System.out.println(superClass.getName());
    
        }
    }
    
  • 获取一个类实现的接口:getInterfaces()

    由于一个类可以实现多个接口,所以一定返回的是一个数组

    public class Test {
        public static void main(String[] args) throws Exception {
    
            Class stringClass = Class.forName("java.lang.String");
    
            //获取String类实现的接口
            Class[] interfaces = stringClass.getInterfaces();
            for(Class c : interfaces){
                System.out.println(c.getName());
            }
            //java.io.Serializable
    		//java.lang.Comparable
    		//java.lang.CharSequence
    
        }
    }
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值