Jdbc笔记02
- 1、class类
- 1.1、反射是什么
- 1.2、如何获得一个类对应的Class对象
- 1.3、Class类常用方法
- 1. `getName()`
- 2. `getSimpleName()`
- 3. `getPackage()`
- 4. `getSuperclass()`
- 5. `getInterfaces()`
- 6. `getFields()`
- 7. `getDeclaredFields()`
- 8. `getMethods()`
- 9. `getDeclaredMethods()`
- 10. `getConstructors()`
- 11. `getDeclaredConstructors()`
- 12. `newInstance()`
- 13. `isInterface()`
- 14. `isArray()`
- 15. `isPrimitive()`
- 16. `getModifiers()`
- 17. `getClassLoader()`
- 18. `getResourceAsStream(String name)`
- 19. `getAnnotation(Class<T> annotationClass)`
- 20. `getDeclaredAnnotations()`
- 1.4、实际用处
- 2、反射与数据库
1、class类
1.1、反射是什么
java程序先经过编译器编译,生成class文件,而class文件的执行场所是在jvm中。
如何要定义一个类来描述所有类的共同特征,应该如何来设计?
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对象
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()
返回类的全限定名(包括包名)。
String className = clazz.getName();
2. getSimpleName()
返回类的简单名称(不包括包名)。
String simpleName = clazz.getSimpleName();
3. getPackage()
返回类的包信息。
Package pkg = clazz.getPackage();
4. getSuperclass()
返回类的直接父类。
Class<?> superClass = clazz.getSuperclass();
5. getInterfaces()
返回类实现的接口数组。
Class<?>[] interfaces = clazz.getInterfaces();
6. getFields()
返回类的所有 public
字段,包括继承的字段。
Field[] fields = clazz.getFields();
7. getDeclaredFields()
返回类的所有字段,包括 private
和 protected
,但不包括继承的字段。
Field[] declaredFields = clazz.getDeclaredFields();
8. getMethods()
返回类的所有 public
方法,包括继承的方法。
Method[] methods = clazz.getMethods();
9. getDeclaredMethods()
返回类的所有方法,包括 private
和 protected
,但不包括继承的方法。
Method[] declaredMethods = clazz.getDeclaredMethods();
10. getConstructors()
返回类的所有 public
构造方法。
Constructor<?>[] constructors = clazz.getConstructors();
11. getDeclaredConstructors()
返回类的所有构造方法,包括 private
和 protected
。
Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
12. newInstance()
创建类的新实例(需要类具有无参构造方法)。
Object instance = clazz.newInstance();
13. isInterface()
判断类是否是接口。
boolean isInterface = clazz.isInterface();
14. isArray()
判断类是否是数组。
boolean isArray = clazz.isArray();
15. isPrimitive()
判断类是否是基本数据类型。
boolean isPrimitive = clazz.isPrimitive();
16. getModifiers()
返回类的修饰符(如 public
, static
等),可以用 Modifier
类的静态方法来解析。
int modifiers = clazz.getModifiers();
boolean isPublic = Modifier.isPublic(modifiers);
17. getClassLoader()
返回类的类加载器。
ClassLoader classLoader = clazz.getClassLoader();
18. getResourceAsStream(String name)
获取资源文件的输入流。
InputStream inputStream = clazz.getResourceAsStream("config.properties");
19. getAnnotation(Class<T> annotationClass)
获取类的指定注解。
Annotation annotation = clazz.getAnnotation(MyAnnotation.class);
20. getDeclaredAnnotations()
获取类上的所有注解。
Annotation[] annotations = clazz.getDeclaredAnnotations();
1.4、实际用处
假设你有一个类MyClass,定义如下
public class MyClass {
private MyClass() {
// 私有无参构造器
}
private String name;
private String getName() {
return name;
}
private void setName(String name) {
this.name = name;
}
}
你可以使用反射机制来,创建对象,给对象中的私有属性赋值,调用其中的私有方法
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
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;
}