目录
主要内容
1.反射的基本知识
2.Class、Field、Method、Constructord的常用方法
3.JDBC利用反射的封装
反射的作用
可以实现动态创建对象和编译,提现出很大的灵活性(运行期间)
公共的代码
package com.sofwin.work;
public class Account {
private String name ;
private Integer money;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getMoney() {
return money;
}
public void setMoney(Integer money) {
this.money = money;
}
@Override
public String toString() {
return "Account [name=" + name + ", money=" + money + "]";
}
}
package com.sofwin.work;
import java.io.Serializable;
public class Student implements Serializable {
}
一、什么是反射?
在运行期间动态的获取类、方法的相关信息
Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法、类,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键。基本上以后的框架底层都是用到了反射机制
二、类加载的过程
1.加载
将编译生产的字节码文件加载到jvm中(运行时区的方法区)
2.连接
验证:验证字节码是否合法
准备:为静态成员变量分配空间
解析:将java中的符号引用改为直接引用
3.初始化
三、类加载的时机
1.new 对象
2.调用静态方法
3.调用静态成员变量
4.子类调用父类的构造方法
四、类对象
类:是对象的模板
对象:是类的实例、
类对象:类对象就是描述这种类,有什么方法,有什么属性等。
特点:有且仅有一个类对象。该类的所以实例共用一个类对象
验证该类的所以实例共用一个类对象
package com.sofwin.pojo;
import java.io.Serializable;
public class User implements Serializable {
private Integer id;
private String name ;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Demo {
public static void main(String[] args) {
User user=new User();
User user2=new User();
//类对象
Class clazz1=User.class;
Class clazz2=user.getClass();
Class clazz3=user2.getClass();
System.out.println(clazz1==clazz2);
System.out.println(clazz1==clazz3);
System.out.println(clazz2==clazz3);
}
}
最后结果都是true ---这说明了 有且仅有一个类对象。该类的所以实例共用一个类对象
五、类加载器
根类加载器 bootstrap classloader
用于加载jdk中lib中的.jar的文件中的类
扩展类加载器 extention classloader
用于加载jdk中lib中ext下的类
系统类加载器 system classloader
用于加载我们自定义的类和第三方框架提供的类 (druid中的java类的加载)
自定义类加载器
六、类对象的三种获取方式
1.static Class forName(String className) --通过全限类名来获取类对象
2.通过类名点class属性来获取类对象
3.通过对象实例的getClass()方法来获取类对象
class Demo {
public static void main(String[] args) {
User user=new User();
User user2=new User();
//类对象的三种创建方式
//1.类名点class属性获取类对象
Class clazz1=User.class;
//2.对象名的getClass()方法
Class clazz2=user.getClass();
Class clazz3=user2.getClass();
//3.forName来获取
Class clazz111=Class.forName("com.sofwin.pojo.User");
}
}
七、类对象的常用API
方法名 | 返回结果 | 描述 |
forName(String className) --静态的 | Class | 通过全限定名来获取类对象 |
getClassLoader() | ClassLoader | 获取类加载器 |
getName() | String | 返回该类对象的全限定名称 |
getModifiers() | int | 获取该类对象的修饰符 |
. getSuperclass() | Class | 返回该类对象的父类 因为java是单继承因此是一个 |
getInterfaces() | Class[] | 获取类的所有接口 --注意这里的接口这是指是这个类 不包含其父类的接口 |
newInstance | Object | 利用反射创建对象 ---注意这里的类一定要有无参构造方法才能创建(依赖无参构造创建) |
常用反射对应修饰符的常量表
package com.sofwin.work;
/**
* Class类对象的常用方法
* @author wentao
*
*/
public class ClassDemo {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
//Class的相关方法
//1.static Class forName(String className) --通过全限类名来获取类对象
//可能出现的异常 ---> ClassNotFoundException 无法找到指定的类异常
Class User = Class.forName("com.sofwin.work.User");
System.out.println(User); //class com.sofwin.work.User
//2.ClassLoader getClassLoader() --放回类的加载器
ClassLoader classLoader = User.getClassLoader(); //sun.misc.Launcher$AppClassLoader@1d16e93
System.out.println(classLoader);
//3.String getName() 返回该类对象的全限定名称
String name = User.getName();
System.out.println(name); //com.sofwin.work.User 全限定类名 包.类
//4.int getModifiers() 获取该类对象的修饰符 ---public对应的是1
/*
* public static final int ABSTRACT 1024
public static final int FINAL 16
public static final int INTERFACE 512
public static final int NATIVE 256
public static final int PRIVATE 2
public static final int PROTECTED 4
public static final int PUBLIC 1
public static final int STATIC 8
public static final int STRICT 2048
public static final int SYNCHRONIZED 32
public static final int TRANSIENT 128
public static final int VOLATILE 64
*
* */
int modifiers = User.getModifiers();
System.out.println(modifiers); //1
//5.Class getSuperclass() 返回该类对象的父类 因为java是单继承因此是一个
Class superclass = User.getSuperclass();
System.out.println(superclass.getName()); //java.lang.Object
//6.Class[] getInterfaces() 获取类的所有接口 --注意这里的接口这是指是这个类 不包含其父类的接口
Class[] interfaces = User.getInterfaces();
for( Class clazz:interfaces) {
System.out.println(clazz.getName());
}
//7.T newInstance 利用反射创建对象 ---注意这里的类一定要有无参构造方法才能创建(依赖无参构造创建)
Object newInstance = User.newInstance();
System.out.println(newInstance); //User [id=null, name=null]
}
}
八、Field的常用API
方法名 | 返回结果 | 描述 |
getFields() | Field[] | 获取所以public修饰的成员变量 |
getDeclaredFields() | Field[] | 获取所有的成员变量 |
getField(String name) | Field | 通过名称来获取public修饰成员变量 |
getDeclaredField(String name) | Field | 通过名称来获取成员变量对象 |
.get类型(Object obj) | Object | obj对象的当前属性的值 |
set类型(Object obj) | Class[] | obj对象的当前属性的值 |
package com.sofwin.work;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
/**
* Class类对象的常用方法
* @author wentao
*
*/
public class FieldDemo {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException {
//Constructor的相关方法
//获取类对象
Class User = Class.forName("com.sofwin.work.User");
User user1=new User(100,"xiaowang");
//1.Field[] getFields() --获取所以public修饰的成员变量
Field[] fields = User.getFields();
for (Field field : fields) {
System.out.println(field.getName());
}
//2.Field[] getDeclaredFields() --获取所有的成员变量
Field[] fields2 = User.getDeclaredFields();
for (Field field2 : fields2) {
System.out.println(field2.getName()); //id name
}
//3. Field getDeclaredField(String name) 通过名称来获取成员变量对象
//NoSuchFieldException 异常
Field field3 = User.getDeclaredField("id");
System.out.println(field3.getName()); //id
//4. Field getField(String name) 通过名称来获取public修饰成员变量
// Field field4 = User.getField("id");
// System.out.println(field4.getName());
//5.getName() 获取名称 getModifiers() 获取修饰符
System.out.println(field3.getName()); //id
System.out.println(field3.getModifiers()); //2
//6.类型 get类型(Object obj) obj对象的当前属性的值
//这里如果是私有的成员变量要进行暴力破解
field3.setAccessible(true);
Object object = field3.get(user1);
System.out.println(object);
//7.类型 set类型(Object obj) obj对象的当前属性的值
field3.set(user1,200);
System.out.println(user1); //User [id=200, name=xiaowang]
}
}
九、Method的常用API
方法名 | 返回结果 | 描述 |
getMethods() | Method[] | 获取所以public修饰的非构造方法 |
getDeclaredMethods() | Method[] | 获取所有的非构造方法 |
getMethod(String name,Class<?>... parameterTypes) | Method | 通过方法名和参数类型来获取public修饰非构造方法 |
getDeclaredMethod(String name,Class<?>... parameterTypes) | Method | 通过名称和参数类型来获取所有的非构造方法 |
invoke(Object obj, Object... args) | 方法的返回结果相同 | 执行对象的方法 |
package com.sofwin.work;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Class类对象的常用方法
* @author wentao
*
*/
public class MethodDemo {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException {
//Constructor的相关方法
//获取类对象
Class User = Class.forName("com.sofwin.work.User");
User user1=new User(100,"xiaowang");
//1.Method[] getMethods() --获取所以public修饰的非构造方法
Method[] method = User.getMethods();
for (Method method1 : method) {
System.out.println(method1.getName());
}
//2.Method[] getDeclaredMethods() --获取所有的非构造方法
Method[] method2 = User.getDeclaredMethods();
for (Method field3 : method2) {
System.out.println(field3.getName());
}
//3. Method getMethod(String name, Class<?>... parameterTypes) 通过名称和参数类型来获取public非构造方法对象
Method methodt = User.getMethod("setId",Integer.class);
System.out.println(methodt.getName());
//
//4. Method getDeclaredMethod(String name, Class<?>... parameterTypes) 通过名称和参数类型来获取非构造方法对象
Method methodt1 = User.getDeclaredMethod("setId",Integer.class);
System.out.println(methodt1.getName());
//5.getNa me() 获取名称 getModifiers() 获取修饰符 getReturnType() 获取返回值类型
System.out.println(methodt1.getName());
System.out.println(methodt1.getModifiers());
System.out.println(methodt1.getReturnType());
// //6.类型 invoke(Object obj, Object... args) 执行对象的方法
methodt1.invoke(user1, 300);
System.out.println(user1);
//
}
}
十、Constructor的常用API
方法名 | 返回结果 | 描述 |
getConstructors() | Constructor[] | 获取所有public修饰的构造方法 |
getDeclaredConstructors () | Constructor[] | 获取所有的构造方法 |
getConstructor(Class<?>... parameterTypes) | Constructor | 通过构造方法的参数类型来获去构造方法 |
getDeclaredMethod(String name,Class<?>... parameterTypes) | Method | 通过名称和参数类型来获取所有的非构造方法 |
newInstance(Object... initargs) | Object | 这个是与Class类对象对应的 这个是通过参数来创建对象 |
package com.sofwin.work;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* Class类对象的常用方法
* @author wentao
*
*/
public class ConstructorDemo {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
//Constructor的相关方法
//获取类对象
Class User = Class.forName("com.sofwin.work.User");
//1.Constructor[] getConstructors() --获取所以public修饰的构造方法
Constructor[] constructors = User.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor.getName()); //com.sofwin.work.User
}
//2.Constructor[] getDeclaredConstructors() --获取所以的构造方法
Constructor[] constructors2 = User.getDeclaredConstructors();
for (Constructor constructor : constructors2) {
System.out.println(constructor.getName()); //com.sofwin.work.User
}
//3. Constructor getConstructor(Class<?>... parameterTypes) 通过构造方法的参数类型来获去构造方法独享
//出现异常 --NoSuchMethodException
Constructor constructor = User.getConstructor(Integer.class ,String.class);
System.out.println(constructor); //public com.sofwin.work.User(java.lang.Integer,java.lang.String)
//4.getName() 获取名称 getModifiers() 获取修饰符
System.out.println(constructor.getName()); //com.sofwin.work.User
System.out.println(constructor.getModifiers()); //1
//5.Class[] getParameterTypes() 按照声明顺序返回构造方法的参数类型
Class[] parameterTypes = constructor.getParameterTypes();
for (Class class1 : parameterTypes) {
System.out.println(class1); //class java.lang.Integer class java.lang.String
}
//6.T newInstance(Object... initargs) 这个是与Class类对象对应的 这个是通过参数来创建对象
Object newInstance = constructor.newInstance(1,"zhangsan");
System.out.println(newInstance); //User [id=1, name=zhangsan]
}
}
十一、JDBC利用反射来封装工具类
package com.sofwin.work;
public class Account {
private String name ;
private Integer money;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getMoney() {
return money;
}
public void setMoney(Integer money) {
this.money = money;
}
@Override
public String toString() {
return "Account [name=" + name + ", money=" + money + "]";
}
}
package com.sofwin.work;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import com.mysql.cj.xdevapi.PreparableStatement;
public class JdbcUtil {
private static Connection conn;
private static Properties props;
private static Statement stmt;
private static PreparedStatement pstmt;
static {
try {
//创建Properties对象 实现动态的不是死编码
props=new Properties();
InputStream is=User.class.getClassLoader().getResourceAsStream("jdbc.properties");
props.load(is);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//驱动加载只需要一次 因此加入到类代码块中就可以了
try {
Class.forName(props.getProperty("jdbc.driver"));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取Connection连接对象
* @return
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(props.getProperty("jdbc.url"),props.getProperty("jdbc.username"),props.getProperty("jdbc.pwd"));
}
/**
* 静态
* @param sql
* @return
* @throws SQLException
*/
public static List<Map> executeQuery(String sql) throws SQLException {
List<Map> result=new ArrayList();
ResultSet rs =null;
try {
conn=JdbcUtil.getConnection();
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
//获取ResultSet的源对象
ResultSetMetaData metaData = rs.getMetaData();
//获取到列的数量
int columnCount=metaData.getColumnCount();
while(rs.next()) {
Map map =new HashMap();
for(int i=1;i<=columnCount;i++) {
String columnLabel = metaData.getColumnLabel(i);
Object obj=rs.getObject(columnLabel);
map.put(columnLabel, obj);
}
//添加进去
result.add(map);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
//关闭资源
JdbcUtil.closeAll(conn, stmt, rs);
}
return result;
}
/**
* 动态sql语句
* @param sql
* @param parms
* @return
* @throws SQLException
*/
public static List<Map> executeQuery2(String sql,Object...parms) throws SQLException {
List<Map> result=new ArrayList();
ResultSet rs =null;
try {
conn=JdbcUtil.getConnection();
pstmt = conn.prepareStatement(sql);
//占位符赋值
if(parms!=null&&parms.length>0) {
for(int i=0;i<parms.length;i++) {
pstmt.setObject(i+1, parms[i]);
}
}
rs = pstmt.executeQuery();
//获取ResultSet的源对象
ResultSetMetaData metaData = rs.getMetaData();
//获取到列的数量
int columnCount=metaData.getColumnCount();
while(rs.next()) {
Map map =new HashMap();
for(int i=1;i<=columnCount;i++) {
map.put(metaData.getColumnLabel(i), rs.getObject(i));
}
//添加进去
result.add(map);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
//关闭资源
JdbcUtil.closeAll(conn, pstmt, rs);
}
return result;
}
/**
* 反射 更加复合面向对象的思想
* @param sql
* @param obj 要封装的类对象
* @return
* @throws SQLException
*/
public static <T> List<T> executeQuery3(String sql,Class obj) throws SQLException {
List result=new ArrayList();
ResultSet rs =null;
try {
conn=JdbcUtil.getConnection();
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
//获取ResultSet的源对象
ResultSetMetaData metaData = rs.getMetaData();
//获取到列的数量
int columnCount=metaData.getColumnCount();
while(rs.next()) {
//要封装的类型必须有无参的构造方法
Object map =obj.newInstance();
//属性对应列 我们这里规定属性名和列名是相同的
for(int i=1;i<=columnCount;i++) {
//列名
String columnLabel = metaData.getColumnLabel(i);
//获取到成员变量的对象
Field field=obj.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(map, rs.getObject(columnLabel));
}
//添加进去
result.add(map);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
//关闭资源
JdbcUtil.closeAll(conn, stmt, rs);
}
return result;
}
/**
* 关闭资源的方法
* @param conn
* @param stmt
* @param rs
* @throws SQLException
*/
public static void closeAll(Connection conn, Statement stmt,ResultSet rs) throws SQLException {
if(rs!=null) rs.close();
if(stmt!=null) stmt.close();
if(conn!=null) conn.close();
}
}