java使⽤反射编写通⽤DAOT
前⾔
反射在框架中的应⽤还是很多的,⽐如spring框架⾥⾯AOP⽤到的动态代理,⽽动态代理就是基于反射的。本⽂主要通过学习java的反射,最后编写通⽤的DAO类。最近在复习java web,在做数据库访问的时候做了⼀个事情。
写⼀个CustomerDAO类(获取数据库连接,执⾏sql,获取resultSet,获取对象,关闭数据库等操作),⽤于根据⽤户名来获取⼀个⽤户对象。这个时候有⼀个新的需求,需要根据根据学号来获取⼀个学⽣对象,⼜需要编写⼀个StudentDAO类。当有更多的需求是时,我们就需要写⼤量的重复性代码。解决这个问题最好的⽅法是把他们公共的部分都提取出来做⼀个类。也就是说把获取⼀个类对象的⽅法抽取出来。
public class DAO<T>{
//sql表⽰需要执⾏的sql语句,args表⽰查询⽤到的参数,⽐如可以根据学号,姓名等进⾏查询
T getObject(String sql, Object ... args){
//获取数据库连接
//执⾏sql
//......
//关闭连接
}
}
这⾥⽤到了泛型,这个⽅法可以理解为返回的是⼀个随便什么类对象。那么问题来了,我们通过sql执⾏完查询之后,怎么知道他到底要返回什么样的对象呢。这⾥就需要⽤到反射了。
1.什么是反射
先说⼀下反射都有些什么功能:
1. 在运⾏时可以构造⼀个类对象
2. 可以获取这个类的属性
3. 可以获取他的⽅法
反射就是在运⾏时可以获取⼀个类的内部信息的⼀个机制。⽤前⾯提到的来解释,在编写继承DAO< T >的类的时候,T可能写成Customer,也可能是Student;
public class CustomerDAO extends DAO<Customer>{
public Costomer getCustomer(long CustomerId){
String sql ="SELECT * FROM student_tb WHERE ID = ?";
return getObject(sql,CustomerId);
}
}
⽽在DAO< T >中我们需要从DAO< Customer >获取Customer类,并且在执⾏完sql过后还要把获取到的属性封装成⼀个Customer。这个过程中我们获取Customer类,还可以造⼀个对象,还可以执⾏这个对象的⽅法。这个过程就是⼀个反射。有的时候我们可能就知道⼀个对象,甚⾄就知道⼀个全类名。想要获取这个类的其他信息,就需要⽤到反射。
2.反射需要掌握哪些内容?
1. Class类
2.获取⽅法Method
3.获取属性
3.Class类
注意这⾥的Class中的"C"是⼤写
3.1Class是什么
Class类的实例表⽰正在java程序中运⾏的类。Class封装了这个运⾏的类的属性、⽅法等信息。在Object类中可以发现有⼀个⽅法是:getClass();在⽂档中它的解释是返回运⾏时类。这个类⾥⾯有很多⽅法,⽐如获取这个运⾏类的名称,获取它的⽅法,还可以执⾏⼀些⽅法等等。
3.2获取Class的⽅式
⽅式⼀:通过类的class属性。已知类名
Class clazz = String.class;
⽅式⼆:通过getClass()⽅法来获取。已经有对象的情况
Class clazz ="这是⼀个字符串".getClass();
⽅式三:通过全类名的⽅式获取。需要知道全类名
Class clazz = Class.forName("java.lang.String");
⽅式三可能⽤的⽐较多,⽐如我们在使⽤spring 的时候⽤到 IOC 容器的时候,配置⼀个bean就是⽤的这种⽅式。
另外还有⼀个很重要的⽅法就是 newInstance(); 在后⾯我们会⽤到,可以使⽤这个⽅法创建⼀个实例,前提是这个类要有默认的构造⽅法。 所以我在编写⼀个实体类的时候,写了带参数的构造⽅法就⼀定要写⼀个⽆参数的构造⽅法。(根据java基础我们知道,如果不写构造⽅法,系统会默认创建⽆参数的构造⽅法。⼀旦写了构造⽅法就不会默认创建了)
4.获取⽅法
⽅法也有相关的封装类------Method,在Class的对象clazz⾥⾯可以获取,
获取Method的⽅法有:
⽅法描述
public static void main(String[] args)throws ClassNotFoundException {
Class clazz = Customer.class;
Method[] methods = Methods();
//Method[] methods = DeclaredMethods();
for(int i =0; i < methods.length; i++){
System.out.println(methods[i].getName());
}
}
}
class Customer{
String name;
String age;
public void publicSayHello(){
System.out.println("Hello!!");
}
private void privateSayHello(String name){
System.out.println("Hello "+name);
}
}
下⾯是Methods();执⾏的结果。它能够获取⽗类的Method。所有类的⽗类都是Object,所以会有equals、wait等⽅法。
这是DeclaredMethods()执⾏的结果
我们还可以通过⽅法名和参数类型来获取⼀个Method对象
public static void main(String[] args)throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException { Class clazz = Customer.class;
Method method = DeclaredMethod("publicSayHello",String.class);
System.out.Name());
Object obj = wInstance();//使⽤newInsstance()可以创建⼀个对象
methods.invoke(obj,"阿璐4r");//可以通过这个invoke执⾏获取到的⽅法,obj代表对象后⾯表⽰参数
}
}
class Customer{
String name;
String age;
public void publicSayHello(String name){
System.out.println("Hello!!"+ name);
}
}
通过看api⽂档会发现还有很多相关的⽅法,这⾥不⼀⼀说了
5.获取属性
关于属性/字段也有⼀个相应的封装类Field。Field的使⽤基本上和Method差不多
5.1获取字段
⽅法描述
获取字段相关代码:
public class TestMain {
public static void main(String[] args)throws NoSuchFieldException {
Class clazz = Student.class;
System.out.println("获取Student中的全部字段");
Field[] fields = DeclaredFields();
for(Field field : fields){
System.out.Name());
}
System.out.println("根据字段名来获取字段");
Field field = DeclaredField("name");
System.out.Name());
}
}
class Student{
private Integer id;
String name;
}
5.2设置和获取字段的值
public class TestMain {
public static void main(String[] args)throws NoSuchFieldException, IllegalAccessException {
Student student =new Student(110,"阿璐4r");
Class clazz = Class();
Field field = DeclaredField("name");
//设置字段的值
field.set(student,"修改后的值");
//获取字段的值
Object val = (student);
System.out.println(val);
}
}
class Student{
private Integer id;
String name;
public Student(){
}java怎么编写
public Student(Integer id, String name){
this.id = id;
this.name = name;
}
public void setId(Integer id){
this.id = id;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
}
这⾥值得我们⼀说的是,字段值的设置和修改是通过实体类的getXxx,setXxx⽅法的。这就是我们为什么在写实体类的时候需要写get,set⽅法,其实他留给了反射来使⽤。 注意的是get、set的⽅法名的写法是有讲究的,如:getName。get后⾯是字段名,但第⼀个字母⼤写。
6.回到最初的问题
对反射有了⼀个⼤致的了解了,现在在回到开始的问题。这个时候我们就可以引⼊⼀个新的技巧。先上代码。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论