目录

一. 概述 

1. 前提

2.定义:

3.作用:

4.如何获取类信息:

5. Class类

1.  获得任意类的class对象

2. Java中创建对象的方式

3.通过Class类获得类中属性

4. 通过Class类对象 获得类中的方法

5.举例

6. 反射的优缺点

(1)优点:

(2)缺点:


一. 概述 

1. 前提

已知一个类,通过new创建这个类的对象, 使用对象去调用属性和方法. 用哪个对象,就在代码中new

在业务代码中这样写没有问题,而对于框架来说,这样写就不行了.

由于框架要处理项目中任意的类,为任意类创建出一个实例(对象)

所以框架需要满足一套机制,即只需要写一套代码,就可以创建任意类对象

    在接触框架之后, 用法就发生了一些变化:

2.定义:

       程序在运行时只需要知道字符串类地址,就可以创建该类的对象,能够动态获取类信息,动态创建对象,并且能够调用任意对象的方法或操作其属性的机制称为Java的反射机制

3.作用:

       根据类的地址(字符串类地址"com.ffyc.news.model.Admin"),动态获得类信息,动态创建对象,调用对象的属性和方法

4.如何获取类信息:

java.long.Class  类

在方法区中(存储类信息) ,  为每一个类创建一个class类的对象,可以通过class类的对象获取他所表示的类中的任何信息

一个Class类对象表示一个运行时的Java类信息,我们可以通过class类提供的方法,获取类中的信息,并创建类的对象,所有Class类是Java反射机制的根基

Class-----类型    Method------方法    Filed------属性

5. Class类

1.  获得任意类的class对象

(1).已知类的字符串地址  Class.forName();

(2).类名.class

(3).对象名.getClass()

package com.ffyc.javareflect;

public class User {
    private String account;
    private  String password;
    public String phone;
    public String address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public User(){
        System.out.println("user无参构造方法");
    }
    public User(String account, String password, String phone) {
        this.account = account;
        this.password = password;
        this.phone = phone;
    }

    public void eat(){
        System.out.println("无参eat");
    }
    public void eat(String foodName){
        System.out.println("有参的eat");
    }

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }
}
package com.ffyc.javareflect;

public class Test1 {
    public static void main(String[] args) throws ClassNotFoundException {
        /*
        传统的类使用:
        User user = new User();//已知有一个user类,我们创建该类的对象
        对于框架来说,面对当得可能是未知的
        */
     /*
    获得任意类的class对象
     */
        //方式一:已知类的字符串地址
        String className ="com.ffyc.javareflect.User";//框架常用
        Class a= Class.forName(className);
        System.out.println(a);

        //方式二:类名.class
        Class b= User.class;//mybatis 中使用 接口.方法
        System.out.println(b);

        //方式三: 对象名.getClass()
        User user = new User();
        Class c = user.getClass();//把当前类型转为Class类型

        System.out.println(b==a);//true 地址相同
        System.out.println(c==a);//true 地址相同
        System.out.println(b==c);//true 地址相同

    }
}

2. Java中创建对象的方式

        1.new对象
        2.io中 对象输出流(反序列化)
        3.反射机制 通过Class类对象中的newInstance();
        4.对象克隆

3.通过Class类获得类中属性

        getField("Phone")     获取类中指定的公共属性
        getFields()                获得类中所有的公共属性
        getDeclaredFields()  获得类中所有的属性

package com.ffyc.javareflect;

import java.lang.reflect.Field;

public class Test2 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {

   
        String className ="com.ffyc.javareflect.User";
        //获得类的class对象
        Class cl =Class.forName(className);
        //调用 Class类中的newInstance() 还会调用类中无参的构造方法,创建出一个对象
        Object obj = cl.newInstance();
        System.out.println(obj);//输出对象

        /*
        通过Class类获得类中属性
        getField("Phone") 获取类中指定的公共属性
        getFields()       获得类中所有的公共属性
        getDeclaredFields() 获得类中所有的属性
         */

        Field accField = cl.getField("account");
        System.out.println(accField);//拿不到,因为account是私有的,只能拿公共的

        Field[] pubfields = cl.getFields();
        System.out.println(pubfields.length);
            for(Field field:pubfields){
                field.set(obj,"aaa");
                System.out.println(field);
            }

        Field[] fields = cl.getDeclaredFields();
            for(Field field:fields){
                System.out.println(field);//输出所有属性
                field.setAccessible(true);//设置对私有属性是否可以操作的开关,默认关闭
                field.set(obj,"aaaa");//给属性赋值
                System.out.println(field.get(obj));//拿到属性的值
            }



    }
}

4. 通过Class类对象 获得类中的方法

getMethods() 获得类中所有的公共方法 

package com.ffyc.javareflect;

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

public class Test3 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
        /*
        Java中创建对象的方式
        1.new对象
        2.io中 对象输出流(反序列化)
        3.反射机制 Class类中的newInstance();
        4.对象克隆
        */
        String className ="com.ffyc.javareflect.User";
        //获得类的class对象
        Class cl =Class.forName(className);
        //调用 Class类中的newInstance() 还会调用类中无参的构造方法,创建出一个对象
        Object obj = cl.newInstance();
        
        /*
        通过Class类对象 获得类中的方法
        getMethods() 获得类中所有的公共方法
         */

        Method method = cl.getMethod("eat");
        System.out.println(method);//拿到无参的eat方法
        method.invoke(obj);//调用获得的方法

        //getMethod("方法名",参数类型) 获得指定方法名 指定类型的公共成员方法
        Method method1= cl.getMethod("eat",String.class);
        System.out.println(method1);
        method1.invoke(obj,"凉皮");//给所调用的有参的方法传参
        
    }
}

 5.举例

forName()

newInstance()

getField("phone"); 获得类中指定名称的公共属性

getFields(); 获得类中所有的公共属性

getDeclaredFields(); 获得类中所有属性

getDeclaredFields("phone")

getDeclaredMethods() 获得类中所有的成员方法

getMethods() 获得类中所有公共的成员方法

getMethod("eat");

getDeclaredMethod("eat");

package com.ffyc.javareflect;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class Demo1 {
    /*
    模拟mybatis  自动数据封装
     */
    public static void putData(String classname, Map<String, Object> map) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {

        //获得传入的类地址的class对象
        Class cl = Class.forName(classname);
        //创建一个传入类的对象
        Object obj = cl.newInstance();
        //动态获得类中的属性
        Field[] fields =cl.getDeclaredFields();
        for(Field field: fields){
            //首先获得属性名称(account password color....)
            String name = field.getName();
            System.out.println(name);
            //通过属性的名字找到属性的set方法名
            String methodName ="set"+(char)(name.charAt(0)-32)+(name.substring(1));
            System.out.println(methodName);
            //通过set方法名字获得对应的set方法
            Method setmethod = cl.getMethod(methodName,field.getType());
            setmethod.invoke(obj,map.get(name));//调用方法 赋值
        }
        System.out.println(obj);
    }

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        //map模拟数据库中查询到到的数据
        Map<String,Object> map = new HashMap<>();
                           map.put("account","admin");
                           map.put("password","111");
                           map.put("phone","17511111111");
        //classname 模拟resultType
        String classname = "com.ffyc.javareflect.User";
        Demo1.putData(classname,map);

        Map<String,Object> map1 = new HashMap<>();
        map.put("name","宝马");
        map.put("color","红色");

        //classname 模拟resultType
        String classname1 = "com.ffyc.javareflect.Car";
        Demo1.putData(classname1,map1);
    }

}

6. 反射的优缺点

(1)优点:

       通过反射机制,可以动态获得任意类中的信息,调用任意对象中的方法,增加程序编写的灵活性和代码的复用性 例如框架 -----写一套代码就可以处理任意类 ; 公共组件...

(2)缺点:

       反射机制使用效率低,可以对私有成员进行操作,打破封装性,使用反射机制时,应该尽量避对私有成员进行操作

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐