Jdbc笔记02
- 1、class类
-
- 1.1、反射是什么
- 1.2、如何获得一个类对应的Class对象
- 1.3、Class类常用方法
-
- [1. `getName()`](#1.
getName()
) - [2. `getSimpleName()`](#2.
getSimpleName()
) - [3. `getPackage()`](#3.
getPackage()
) - [4. `getSuperclass()`](#4.
getSuperclass()
) - [5. `getInterfaces()`](#5.
getInterfaces()
) - [6. `getFields()`](#6.
getFields()
) - [7. `getDeclaredFields()`](#7.
getDeclaredFields()
) - [8. `getMethods()`](#8.
getMethods()
) - [9. `getDeclaredMethods()`](#9.
getDeclaredMethods()
) - [10. `getConstructors()`](#10.
getConstructors()
) - [11. `getDeclaredConstructors()`](#11.
getDeclaredConstructors()
) - [12. `newInstance()`](#12.
newInstance()
) - [13. `isInterface()`](#13.
isInterface()
) - [14. `isArray()`](#14.
isArray()
) - [15. `isPrimitive()`](#15.
isPrimitive()
) - [16. `getModifiers()`](#16.
getModifiers()
) - [17. `getClassLoader()`](#17.
getClassLoader()
) - [18. `getResourceAsStream(String name)`](#18.
getResourceAsStream(String name)
) - [19. `getAnnotation(Class<T> annotationClass)`](#19.
getAnnotation(Class<T> annotationClass)
) - [20. `getDeclaredAnnotations()`](#20.
getDeclaredAnnotations()
)
- [1. `getName()`](#1.
- 1.4、实际用处
- 2、反射与数据库
1、class类
1.1、反射是什么
java程序先经过编译器编译,生成class文件,而class文件的执行场所是在jvm中。
如何要定义一个类来描述所有类的共同特征,应该如何来设计?
java
public class Class{
private String name;//类名
private Package pkl//包名
private Constructor[] constructors;//构造方法,可能有多个
private Field[] fields;//字段
private Method[] methods;//方法
private Class<?> interfaces;//实现的接口
private Class<?> superClass;//继承的父类
//Getter & Setter
}
JVM记载类的过程相当于对文件内容进行解析,解析内容就需要找到共有特征,然后再将这特征存储起来,在使用的时候再取出来,通过Class对象反向推到我们编写的类的内容,然后再进行操作,这个过程称为反射
1.2、如何获得一个类对应的Class对象
java
Class<类名> clazz = 类名.class;
Class<? extends 类名> clazz = 对象名.getClass();
Class<? super 类名> clazz = clazz.getSuperClass();
Class clazz = Class.forName("类的全限定名");
Class clazz = 包装类.TYPE;
1.3、Class类常用方法
Class
类是 Java 反射机制的核心,它提供了获取类信息的方法。以下是一些常用的 Class
类方法:
1. getName()
返回类的全限定名(包括包名)。
java
String className = clazz.getName();
2. getSimpleName()
返回类的简单名称(不包括包名)。
java
String simpleName = clazz.getSimpleName();
3. getPackage()
返回类的包信息。
java
Package pkg = clazz.getPackage();
4. getSuperclass()
返回类的直接父类。
java
Class<?> superClass = clazz.getSuperclass();
5. getInterfaces()
返回类实现的接口数组。
java
Class<?>[] interfaces = clazz.getInterfaces();
6. getFields()
返回类的所有 public
字段,包括继承的字段。
java
Field[] fields = clazz.getFields();
7. getDeclaredFields()
返回类的所有字段,包括 private
和 protected
,但不包括继承的字段。
java
Field[] declaredFields = clazz.getDeclaredFields();
8. getMethods()
返回类的所有 public
方法,包括继承的方法。
java
Method[] methods = clazz.getMethods();
9. getDeclaredMethods()
返回类的所有方法,包括 private
和 protected
,但不包括继承的方法。
java
Method[] declaredMethods = clazz.getDeclaredMethods();
10. getConstructors()
返回类的所有 public
构造方法。
java
Constructor<?>[] constructors = clazz.getConstructors();
11. getDeclaredConstructors()
返回类的所有构造方法,包括 private
和 protected
。
java
Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
12. newInstance()
创建类的新实例(需要类具有无参构造方法)。
java
Object instance = clazz.newInstance();
13. isInterface()
判断类是否是接口。
java
boolean isInterface = clazz.isInterface();
14. isArray()
判断类是否是数组。
java
boolean isArray = clazz.isArray();
15. isPrimitive()
判断类是否是基本数据类型。
java
boolean isPrimitive = clazz.isPrimitive();
16. getModifiers()
返回类的修饰符(如 public
, static
等),可以用 Modifier
类的静态方法来解析。
java
int modifiers = clazz.getModifiers();
boolean isPublic = Modifier.isPublic(modifiers);
17. getClassLoader()
返回类的类加载器。
java
ClassLoader classLoader = clazz.getClassLoader();
18. getResourceAsStream(String name)
获取资源文件的输入流。
java
InputStream inputStream = clazz.getResourceAsStream("config.properties");
19. getAnnotation(Class<T> annotationClass)
获取类的指定注解。
java
Annotation annotation = clazz.getAnnotation(MyAnnotation.class);
20. getDeclaredAnnotations()
获取类上的所有注解。
java
Annotation[] annotations = clazz.getDeclaredAnnotations();
1.4、实际用处
假设你有一个类MyClass,定义如下
java
public class MyClass {
private MyClass() {
// 私有无参构造器
}
private String name;
private String getName() {
return name;
}
private void setName(String name) {
this.name = name;
}
}
你可以使用反射机制来,创建对象,给对象中的私有属性赋值,调用其中的私有方法
java
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectionExample {
public static void main(String[] args) {
try {
// 获取 MyClass 类的 Class 对象
Class<?> clazz = Class.forName("MyClass");
// 获取私有的无参构造器
Constructor<?> constructor = clazz.getDeclaredConstructor();
// 设置构造器为可访问
constructor.setAccessible(true);
// 使用构造器创建对象
Object obj = constructor.newInstance();
// 获取私有的 name 字段
Field nameField = clazz.getDeclaredField("name");
// 设置字段为可访问
nameField.setAccessible(true);
// 设置字段值
nameField.set(obj, "Reflection Value");
// 获取私有的 getName 方法
String methodName = "get" + nameField.substring(0,1).toUpperCase() + nameField.substring(1);
Method getNameMethod = clazz.getDeclaredMethod(methodName);
// 设置方法为可访问
getNameMethod.setAccessible(true);
// 调用 getName 方法并获取返回值
String name = (String) getNameMethod.invoke(obj);
System.out.println("Name: " + name);
// 获取私有的 setName 方法
methodName = "set" + nameField.substring(0,1).toUpperCase() + nameField.substring(1);
Method setNameMethod = clazz.getDeclaredMethod(methodName, nameField.getType());
// 设置方法为可访问
setNameMethod.setAccessible(true);
// 调用 setName 方法
setNameMethod.invoke(obj, "New Value");
// 再次调用 getName 方法
name = (String) getNameMethod.invoke(obj);
System.out.println("New Name: " + name);
} catch (Exception e) {
e.printStackTrace();
}
}
}
2、反射与数据库
数据库查询出的每一条数据基本上都会封装为一个对象,数据库中的每一个字段值都会存储在对象相应的属性中。如果查询结果的每一个字段都与
例如,通过参数给定Class,就可以通过反射进行封装对象并返回,就不用每一个对象都要写一个查询函数了,只需要一个查询函数给定参数(String sql,Class clazz,Object... params)。
如果字段与属性名不同,例如:字段为good_id,而属性是goodId怎么办呢?
在select的时候 给good_id起一个别名叫 goodId即可解决。
在某些场景下,JDBC和反射可以结合使用,以实现更灵活的功能。例如:
- 动态ORM(对象关系映射) :通过反射,可以将数据库查询结果(
ResultSet
)动态映射到Java对象中,而不需要手动编写大量的赋值代码。 - 动态生成SQL语句 :通过反射获取类的字段信息,动态生成
INSERT
、UPDATE
等SQL语句。
示例:动态ORM
java
public <T> T mapResultSetToObject(ResultSet rs, Class<T> clazz) throws Exception {
T obj = clazz.getDeclaredConstructor().newInstance();
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();
for (int i = 1; i <= columnCount; i++) {
String columnName = metaData.getColumnName(i);
Field field = clazz.getDeclaredField(columnName);
field.setAccessible(true);
field.set(obj, rs.getObject(i));
}
return obj;
}