java高级--反射

这篇博客探讨了Java的反射机制,它是框架设计的关键。详细介绍了如何获取反射类Class,包括Class.forName、类名.class和对象.getClass()三种方式。接着讲解了通过反射获取Field属性对象和Method方法对象,并列举了Field属性对象的方法如getName、setAccessible和set/get。进一步讨论了Method类中的invoke方法,以及获取Annotation注解对象的方法。最后提到了手撕ORM框架的实践过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 什么是反射?

反射是框架设计的灵魂,框架:它是一个半成品,可以拿来使用,添加上自己的业务代码。提高开发效率。

反射就是把类中成员抽取成其他类的过程。这就是反射。


2. 如何获取反射类Class

(1) 通过Class.forName获取反射对象.

Class.forName("全路径")
--spring它就是使用的该模式<bean class="全路径">

(2)通过类名.class获取

类名.class;
---代理类--->SqlSession.getMapper(StudentDao.class)

(3) 通过对象.getClass()方法获取

对象.getClass();
---当知道对象时可以通过这种方式获取反射对象
​​​​

public class Test01 {
    public static void main(String[] args) throws ClassNotFoundException {
        //1.通过Class.forName来获取反射类对象。
        Class aClass = Class.forName("demo.People");
        //2.通过类名调用.class获取反射类对象
        Class aClass1 = People.class;
        //3.通过对象获取反射类对象
        People p=new People();
        Class aClass2 = p.getClass();

        //思考:上面三个反射对象的引用地址是否一致! 是一致的。 一个类只会被加在到内存中一次。
        System.out.println(aClass==aClass1);
        System.out.println(aClass2==aClass1);
    }
}


3. 根据反射类获取对应的类对象。

public class Test02 {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException {
        //1.获取反射类对象
        Class<People> aClass = People.class;
        //2.由反射类创建类对象---调用为无参构造函数
        People people = aClass.newInstance();
        People people2 = aClass.newInstance();

        //3.他们的地址是否相同
        System.out.println(people==people2);
    }
}

4. 通过反射获取对应的Field属性对象

aclass.newInstance();

public class Test {
    public static void main(String[] args) throws Exception {
        Class<?> aClass = Class.forName("demo.People");

        //获取本类中指定的属性对象
        Field name = aClass.getDeclaredField("name");
        System.out.println(name);
        //获取本类以及父类中指定的属性---必须为public修饰的。
        Field name1 = aClass.getField("sex");
        System.out.println(name1);

        //获取本类中所有的属性对象
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field field:declaredFields) {
            System.out.println(field);
        }

        //获取本类以及父类中所有public修饰的属性对象
        Field[] fields = aClass.getFields();
        for (Field field:
             fields) {
            System.out.println(field);
        }

    }
}

4.1 Field属性对象中常见的方法。

getName():获取属性名
setAccessible(true):设置属性可访问。
set(o,v):为对象o的属性赋值v
get(o):获取对象o的属性值

public static void main(String[] args) throws Exception {
        Class<People> peopleClass = People.class;

        Field nameField = peopleClass.getDeclaredField("name");
        //1.获取属性的名称
        String name = nameField.getName();
        System.out.println("属性名称:"+name);

        //2.为属性赋值.
        //Object obj,对象
        // Object value
        People people = peopleClass.newInstance();
        System.out.println(people);

        nameField.setAccessible(true);//为nameField设置可访问权限,打破了封装性
        nameField.set(people,"张三");
        System.out.println(people);

        //3.获取属性值
        Object o = nameField.get(people);
        System.out.println(o);

        //nameField.getAnnotation();//获取nameField属性上的注解对象
    }


5. 通过反射获取对应的Method方法对象

public class Test03 {
    public static void main(String[] args) throws Exception {
        Class<People> aClass = People.class;

        //获取本类中所有的方法。
        Method[] declaredMethods = aClass.getDeclaredMethods();
        for (Method method:declaredMethods) {
            System.out.println(method);
        }


        System.out.println("======================================================");
        //获取本类和父类中所有public修饰的方法
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }

        System.out.println("**************************************************************");
        //本类中指定的 方法对象
        Method fun = aClass.getDeclaredMethod("fun");
        System.out.println(fun);
        Method setName = aClass.getDeclaredMethod("setName",String.class);
        System.out.println(setName);

        //获取本类以及父类中指定名称的方法对象
        Method equals = aClass.getMethod("equals", Object.class);
        System.out.println(equals);

    }
}

5.1Method类中常见的方法

  //method.invoke(对象,方法参数值);
 invoke(people,"15");//回调。动态代理 


6. 如何获取对应的Annotation注解对象

public class Test {
    public static void main(String[] args) throws Exception{
        Class<Student> aClass = Student.class;

        //获取类对象的指定注解
        MyAnnotation annotation = aClass.getAnnotation(MyAnnotation.class);
        System.out.println(annotation.value());


        Field idField = aClass.getDeclaredField("id");
        MyAnnotation annotation1 = idField.getAnnotation(MyAnnotation.class);
        System.out.println(annotation1.value());
        System.out.println(annotation1.sex());

    }
}

7. 手撕ORM框架

 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zjh</groupId>
    <artifactId>ORM0714</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
    </dependencies>

</project>

entity

package com.zjh.entity;

import com.zjh.annotation.TableField;
import com.zjh.annotation.TableId;
import com.zjh.annotation.TableName;
import lombok.Data;

import java.lang.annotation.Target;

/**
 * @author: jh
 * @create: 2022/7/14
 */
@Data
@TableName(value = "user")
public class User {
    @TableId
    private Integer id;
    @TableField("userName")
    private String username;
    private String password;
}

UserDao

package com.zjh.dao;

import com.zjh.entity.User;
import com.zjh.util.BaseDao;

/**
 * @author: jh
 * @create: 2022/7/14
 */
public class UserDao extends BaseDao<User> {
}

自定义注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableId {
    String value() default "id";
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TableName {
    String value();/*表名*/
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableField {
    String value();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TablePromaryKey {
    String value();
}

DButils

package com.zjh.util;

import java.sql.*;

/**
 * @author: jh
 * @create: 2022/7/14
 */
public class DBUtils {
    private static String driverName="com.mysql.cj.jdbc.Driver";
    private static String url="jdbc:mysql://localhost:3306/mydb?severTimezone=Asia/Shanghai";
    private static String username="root";
    private static String password="123456";
    public static Connection getConn() throws Exception{
        Class.forName(driverName);
        Connection connection = DriverManager.getConnection(url,username,password);
        return connection;
    }

    public static void closeAll(ResultSet rs, PreparedStatement ps,Connection connection) {
        try {
            if (rs!=null){
                rs.close();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        try {
            if (ps!=null){
                ps.close();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        try {
            if (connection!=null){
                connection.close();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
}

BaseDao

package com.zjh.util;

import com.zjh.annotation.TableField;
import com.zjh.annotation.TableId;
import com.zjh.annotation.TableName;
import com.zjh.annotation.TablePromaryKey;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

/**
 * @author: jh
 * @create: 2022/7/14
 */
public class BaseDao<T>{
    private Class<?> clazz;

    public BaseDao(){
        Class<? extends BaseDao> aClass = this.getClass();
        ParameterizedType genericSuperclass = (ParameterizedType) aClass.getGenericSuperclass();
        Type[] actualTypeArguments = genericSuperclass.getActualTypeArguments();
        clazz= (Class<?>) actualTypeArguments[0];
    }

    /*查询单个*/
    public T selectById(Object id) throws Exception {
        StringBuffer sql = new StringBuffer("select * from ");
        //获取表名
        TableName tableNameAnnotation = clazz.getAnnotation(TableName.class);
        String tableName = "";
        //是否存在该注解
        if (tableNameAnnotation != null) {
            tableName = tableNameAnnotation.value();
        } else {
            tableName = clazz.getSimpleName();
        }
        sql.append(tableName + " where ");
        Field[] declaredFields = clazz.getDeclaredFields();
        boolean f=false;
        for (Field declaredField : declaredFields) {
            declaredField.setAccessible(true);
            TableId tableId = declaredField.getAnnotation(TableId.class);
            if(tableId!=null){
                sql.append(tableId.value()+"='"+id+"'");
                f=true;
                break;
            }
        }
        if(f==false){
            throw new RuntimeException("没有添加主键注解");
        }
        Connection conn = DBUtils.getConn();
        PreparedStatement ps = conn.prepareStatement(sql.toString());
        ResultSet rs = ps.executeQuery();
        Object o = clazz.newInstance();
        while (rs.next()){
            Field[] declaredFields1 = clazz.getDeclaredFields();
            for (Field declaredField : declaredFields1){
                declaredField.setAccessible(true);
                TableField tableField = declaredField.getAnnotation(TableField.class);
                if (tableField == null){
                    declaredField.set(o,rs.getObject(declaredField.getName()));
                }else {
                    declaredField.set(o,rs.getObject(tableField.value()));
                }
            }
        }
        return (T) o;
    }

    /*查询所有*/
    public List<T> findAll() throws Exception{
        List<T> list = new ArrayList<T>();
        StringBuffer sql=new StringBuffer("select * from ");
        //获取表名
        TableName tableNameAnnotation = clazz.getAnnotation(TableName.class);
        String tableName = "";
        //是否存在该注解
        if (tableNameAnnotation != null) {
            tableName = tableNameAnnotation.value();
        } else {
            tableName = clazz.getSimpleName();
        }
        sql.append(tableName);

        Connection conn = DBUtils.getConn();
        PreparedStatement ps = conn.prepareStatement(sql.toString());
        ResultSet rs = ps.executeQuery();
        while (rs.next()){
            Object o = clazz.newInstance();
            Field[] declaredFields = clazz.getDeclaredFields();
            for (Field declaredField : declaredFields){
                declaredField.setAccessible(true);
                TableField tableField = declaredField.getAnnotation(TableField.class);
                if (tableField == null){
                    TablePromaryKey tablePromaryKey = declaredField.getAnnotation(TablePromaryKey.class);
                    if (tablePromaryKey!=null){
                        declaredField.set(o,rs.getObject(tablePromaryKey.value()));
                    }else {
                        declaredField.set(o,rs.getObject(declaredField.getName()));
                    }
                }else {
                    declaredField.set(o,rs.getObject(tableField.value()));
                }
            }
            list.add((T) o);
        }
        return list;
    }

    //delete from 表名 where 主键=主键值
    public int deleteById(Object id) throws Exception {
        StringBuffer sql = new StringBuffer("delete from ");
        //获取表名
        TableName tableNameAnnotation = clazz.getAnnotation(TableName.class);
        String tableName = "";
        //是否存在该注解
        if (tableNameAnnotation != null) {
            tableName = tableNameAnnotation.value();
        } else {
            tableName = clazz.getSimpleName();
        }
        sql.append(tableName+" where ");

        Field[] declaredFields = clazz.getDeclaredFields();
        boolean flag=false;
        for (Field declaredField : declaredFields) {
            declaredField.setAccessible(true);
            TableId tableId = declaredField.getAnnotation(TableId.class);
            if(tableId!=null){
                sql.append(tableId.value()+"='"+id+"'");
                flag=true;
                break;
            }
        }
        if(flag==false){
            throw new RuntimeException("没有添加主键注解");
        }

        Connection conn = DBUtils.getConn();
        PreparedStatement ps = conn.prepareStatement(sql.toString());
        int i = ps.executeUpdate();
        return i;
    }

    /*修改*/
    //修改--update 表名 set 列名=值,列名=值.... where 主键=值;
    //只能根据注解修改
    public int updateById(T t) throws Exception{
        StringBuffer sql=new StringBuffer("update ");
        //获取表名
        Class<?> aClass = t.getClass();
        TableName tableNameAnnotation = aClass.getAnnotation(TableName.class);
        String tableName = "";
        //是否存在该注解
        if (tableNameAnnotation != null) {
            tableName = tableNameAnnotation.value();
        } else {
            tableName = aClass.getSimpleName();
        }
        sql.append(tableName+" set ");

        String columnValue="";
        String where =" where ";
        //获取所有得属性对象。
        Field[] declaredFields = aClass.getDeclaredFields();
        boolean flag=false;
        for(Field field:declaredFields){
            field.setAccessible(true);
            TableField fieldAnnotation = field.getAnnotation(TableField.class);
            if(fieldAnnotation!=null){
                columnValue+=fieldAnnotation.value()+"='"+field.get(t)+"',";
            }else{
                TableId tableIdAnnotation = field.getAnnotation(TableId.class);
                if(tableIdAnnotation!=null){
                    flag=true;
                    where+=tableIdAnnotation.value()+"='"+field.get(t)+"'";
                }else{
                    columnValue+=field.getName()+"='"+field.get(t)+"',";
                }
            }
        }
        if(flag==false){
            throw  new RuntimeException("没有添加主键注解");
        }
        //去除最后得逗号
        columnValue=columnValue.substring(0,columnValue.lastIndexOf(","));

        sql.append(columnValue).append(where);
        System.out.println(sql);

        Connection conn = DBUtils.getConn();
        PreparedStatement ps = conn.prepareStatement(sql.toString());
        int i = ps.executeUpdate();
        return i;

    }

    /*增加*/
    public int insert(T t){
        try {
            StringBuffer sb = new StringBuffer("insert into ");
            /*获取表名*/
            Class<?> aClass = t.getClass();
            TableName tableNameAnnotation = aClass.getAnnotation(TableName.class);
            String tableName = "";
            if (tableNameAnnotation != null) {
                tableName = tableNameAnnotation.value();
            } else {
                tableName = aClass.getSimpleName();
            }
            sb.append(tableName);

            /*获取反射类对象中所有的属性对象*/
            Field[] declaredFields = aClass.getDeclaredFields();
            /*创建两个集合*/
            List<String> columns = new ArrayList<String>();/*存放所有的列名*/
            List<String> values = new ArrayList<String>();/*存放所有的列值*/
            for (Field declaredField : declaredFields) {
                declaredField.setAccessible(true);
                TableField tableField = declaredField.getAnnotation(TableField.class);
                if (tableField != null) {
                    columns.add(tableField.value());
                } else {
                    columns.add(declaredField.getName());
                }
                values.add("'" + declaredField.get(t) + "'");
            }
            sb.append(columns.toString().replace("[", "(").replace("]", ")"));
            sb.append(" values ");
            sb.append(values.toString().replace("[", "(").replace("]", ")"));

            /*获取连接对象*/
            Connection conn = DBUtils.getConn();
            PreparedStatement ps = conn.prepareStatement(sb.toString());
            int i = ps.executeUpdate();
            return i;
        }catch(Exception e){
            e.printStackTrace();
        }finally{
        }
        return 0;
    }
}

测试

package com.zjh;

import com.zjh.dao.UserDao;
import com.zjh.entity.User;

import java.util.List;

/**
 * @author: jh
 * @create: 2022/7/14
 */
public class Test {
    public static void main(String[] args) throws Exception{
        UserDao userDao = new UserDao();
        User user = new User();

        /*user.setId(19);
        user.setUsername("赵六");
        user.setPassword("12345");
        userDao.insert(user);*/

        /*user.setId(19);
        user.setUsername("李四");
        user.setPassword("123456");
        userDao.updateById(user);*/

        /*userDao.deleteById(19);*/

        /*List<User> list = userDao.findAll();
        System.out.println(list);*/

        User user1 = userDao.selectById(1);
        System.out.println(user1);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值