反射:
程序在运行的时候识别类(接口)的能力,在运行的过程中可以读取元数据。
关于反射的我们一共要知道5个类:
Java.lang.class;
Java.lang.reflect.Constructor;
Java.lang.reflect.Field;
Java.lang.reflect.Method;
Java.lang.reflect.Modifier;
下面我们一个个来说:
Class:
就是用来当反射的入口,用来创建类实例。
public static void equals(Object obj,Object obj1){
Class<?> c=obj.getClass();
Class<?> c1=obj1.getClass();//getclass()是object的,用来返回运行时的类。
if(c==c1){
System.out.println("相等的两个"+c.getSimpleName());
}else{
System.out.println("是不相等的");
System.out.println("其中一个是:"+c.getSimpleName()+"另外一个是:"+c1.getSimpleName());
}
}
getName(),getSimpleName();getSuperClass();getModifiers()时常用的方法。
Class中更为常用的是下面的几组:
Field[] getDeclaredFields();
FieldgetDeclaredField(String);
Field[]getFields();
FieldgetField(String);这四种方法用来获取Field;
ConstructorgetConstructor(Class…c);
Constructor[]getConstructors();
ConstructorgetDeclaredConstructor();
Constructor[]getDeclaredConstructors();这四种方法用来获取Constructor;
Method getMethod (Stringname,Class<?>…args);
Method [] getMethods();
Method getDeclaredMethod(String name,Class<?>…args);
Method []getDeclaredMethods()这四种方法用来获取Method;
这些都是在class中的方法,带有Declared的和不带的区别就在于,带的可以访问private的属性,不带的不行;
Field类:
Field代表一个属性,Field中包括属性名,数据类型,修饰符。
因为这个类可以让我们获得到vo中的所有属性,而属性我们设置的就是mysql数据库中的表中的列名,vo的文件名就是数据库的表名,所以我们可以用Field来拼一个sql语句,动态的进行操作数据库。
public static void insert(Object obj){
Class<?> c=obj.getClass();
StringBuffer sql=new StringBuffer("insert into "+c.getSimpleName()+"(");
StringBuffer sql1=new StringBuffer(")values(");
Field[] fs=c.getDeclaredFields();
for(int i=0;i<fs.length;i++){
if(i!=fs.length-1){
sql.append(fs[i].getName()+",");
sql1.append("?,");
}else{
sql.append(fs[i].getName());
sql1.append("?);");
}
}
sql.append(sql1);
System.out.println(sql);
}
Field常用的方法:getName();getType();getModifiers();
Field因为他的这些方法就可以对属性进行读和写的操作了,对象的属性,值的操作。
用:Object get(Object obj);
Voidset(Object obj,Object value);
来来来再看个简单的栗子,代码里面加上了之前的东西哦….
public static void save(Object obj) throws SQLException {
Class<?> c=obj.getClass();
StringBuffer sql=new StringBuffer("insert into "+c.getSimpleName()+"(");
StringBuffer sql1=new StringBuffer(")values(");
Field[] fs=c.getDeclaredFields();
for(int i=0;i<fs.length;i++){
if(i!=fs.length-1){
sql.append(fs[i].getName()+",");
sql1.append("?,");
}else{
sql.append(fs[i].getName());
sql1.append("?);");
}
}
sql.append(sql1);
Connection conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/java1025?Unicode=true&characterEncoding=UTF-8","root","");
PreparedStatement ps=null;
try{
ps=conn.prepareStatement(sql.toString());
for(int i=0;i<fs.length;i++){
fs[i].setAccessible(true);
ps.setObject(i+1,fs[i].get(obj));
}
ps.execute();
System.out.println("插入成功");
}catch(Exception e){
e.printStackTrace();
}finally{
ps.close();
conn.close();
}
}
(原谅我抛出异常没处理,自己写处理一下吧,不往外面抛出)
上面有一段代码是:setAccessible,设置属性的可访问性的,如果不设置的话,有些private的无法访问。
上课的时候同学问了我一个问题,我觉得good呀,确实是没区分清的孩纸容易疑问,问题如下:在有Declared的方法里面老师说这个是用来获取全部的,那setAccessible方法又是让你获取全部的,这不重复了吗?当然不,有Declared的是可以用来获取私有的Field,Constructor,Method的,而setAccessible是设置你获取完的东西里面的私有的可以访问,就是你要用Declared这个房卡进门,你才能进行后续的操作吖…..
Constructor类:
代表一个类中的构造方法,这个类中封装定义了构造方法;
常用的方法:getName(),getModifiers(),getParameterTypes();newInstance()
Method类:
提供了关于类或接口上的单独的某个方法的信息,代表类中的一个方法的定义,一个method由修饰符,返回值类型,方法名称,参数列表组成;
Method提供的方法有:
getName():获得方法名;
getModifiers():获得修饰符;
getReturnType():返回值类型;
getParameterTypes():参数类型的数组;
invoke(Objectobj,Object…args);方法被调用
public static <T> List<T> getAll(Class<T> c) throws SQLException {
String sql="select * from "+c.getSimpleName();
Connection conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/java1025?Unicode=true&characterEncoding=UTF-8","root","");
PreparedStatement ps=null;
Field[] fs=c.getDeclaredFields();
List<T> list=new ArrayList<T>();
ResultSet rs=null;
try{
ps=conn.prepareStatement(sql);
rs=ps.executeQuery();
while(rs.next()){
T obj=c.newInstance();
for(Field f:fs){
f.setAccessible(true);
f.set(obj,rs.getObject(f.getName()));
}
list.add(obj);
}
}catch(Exception e){
e.printStackTrace();
}
return list;
}