java per.get_Java 中的反射机制

一、什么是Java中的反射:

Reflection 是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说“自审”,并能直接操作程序的内部属性和方法。Java 的这一能力在实际应用中用得不是很多,但是在其它的程序设计语言中根本就不存在这一特性。例如,Pascal、C 或者 C++ 中就没有办法在程序中获得函数定义相关的信息。

Reflection 是 Java 被视为动态(或准动态)语言的关键,允许程序于执行期 Reflection APIs 取得任何已知名称之 class 的內部信息。类中有什么信息,他就能获得什么信息。

在用jdbc连接数据库的时候,用到一句话  Class.forName("com.mysql.jdbc.Driver.class").newInstance(); 那时候还不知道这就是反射,不知道他的具体含义。现在很多开发框架都用到反射机制,hibernate、struts,Spring的依赖注入,都用到了反射机制。另外在Eclipse中,有随笔提示功能,实际上用到的也是java中的反射机制实现的。

二、Java中的Class类

Class has no public constructor. Instead Class objects are constructed automatically by the Java Virtual Machine as classes are loaded and by calls to the defineClassmethod in the class loader.

Java文档中明确说了Class没有公用构造器,这个类是由JVM来创建的,所以我们就不用麻烦了。

那我们如何得到Class对象实例呢,主要有以下三种方法。

packagecom.iip;classPerson {private String name ; //name属性

private int age ; //age属性

public voidsetName(String name){this.name =name ;

}public void setAge(intage){this.age =age ;

}publicString getName(){return this.name ;

}public intgetAge(){return this.age ;

}public String toString(){ //覆写toString()方法

return "姓名:" + this.name + ",年龄:" + this.age ;

}

};public classReflection {public static voidmain(String[] args){

Class> c1 = null;

Class> c2 = null;

Class> c3 = null ; //声明Class对象//三种方法

try{

c1= Class.forName("com.iip.Person") ; //1、Class.forName(包名+类名) 需要捕获ClassNotFoundException异常

}catch(ClassNotFoundException e){

e.printStackTrace() ;

}

c2= Person.class; //2、通过类名.class实例化class对象

c3 = new Person().getClass(); //3、通过对象.getClass()实例化class对象

Person per= null ; //声明Person对象

try{

per= (Person)c1.newInstance() ; //通过 newInstance()实例化对象

}catch(InstantiationException e){e.printStackTrace() ;

}catch(IllegalAccessException e){

e.printStackTrace() ;

}

per.setName("test") ; //设置姓名

per.setAge(30) ; //设置年龄

System.out.println(per) ; //内容输出,调用toString()

}

}

class1,class2,class3便是Class类的对象。可通过这些对象获得X类的所有信息。包括Fields(代表类的成员变量),Methods(代表类的方法),Constructor(代表类的构造方法)

在Class类中,有如下方法。

getName():获得类的完整名字,包名+类名

getFields():获得类的public类型的属性

getDeclaredFields():获得类的所有属性。

getMethods():获得类的public类型的方法。

getDeclaredMethods():获得类的所有方法。

getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。

getConstructors():获得类的public类型的构造方法。

getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。

getDeclaredConstructors() :返回类中所有的构造器,包括私有

newInstance():通过类的不带参数的构造方法创建这个类的一个对象。

之后,我们便可以通过Class类的对象c1的newInstance()方法直接实例化Person类的对象。

public T newInstance() throws InstantiationException,IllegalAccessException

newInstance返回的是一个泛型,因此我们需要强制转换成Person类型。

第一、这种方法必须要求Person类中存在无参构造方法,因为Class的newInstance是不接受参数的,如果我在Person中加入构造方法

public Person(String name,intage){this.setName(name) ;this.setAge(age);

}

类中就只有这一个构造方法,将没有默认提供的无参构造方法,再运行时就会报错。

第二、如果类的构造函数是private的,比如Class,我们仍旧不能实例化其对象。

如果想使用可接受参数的newInstance,需要明确指定要调用的构造方法,并传递参数,但在实际的开发中,一般使用反射实例化的时候,都最好存在一个无参构造函数,这样比较合理些。

获取Person类的构造器 Constructor> cons[] = c1.getConstructors() ;

Constructor> cons[] =c1.getConstructors() ;

Person per= null ; //声明Person对象

try{

per= (Person)cons[0].newInstance("test",30) ; //实例化对象

}catch(IllegalArgumentException e) {

e.printStackTrace();

}catch(InvocationTargetException e) {

e.printStackTrace();

}catch(InstantiationException e){

e.printStackTrace();

}catch(IllegalAccessException e){

e.printStackTrace();

}

下面讲如何获得Person类的所有域。

Field [] f =c1.getDeclaredFields();for (int i = 0; i < f.length; i++) {

Class> r = f[i].getType() ; //得到属性类型

int mo = f[i].getModifiers() ; //得到修饰符的数字

String priv = Modifier.toString(mo) ; //还原修饰符

System.out.print(priv + " ") ;

System.out.print(r.getName()+ " ") ; //得到属性类型

System.out.print(f[i].getName()) ; //输出属性名称

System.out.println(" ;") ;

}

输出结果为 :

privatejava.lang.String name ;private int age ;

如果只想得到公共属性,调用getFields()方法。

其中在 JAVA 反射机制中,Field的getModifiers()方法返回int类型值表示该字段的修饰符。

该修饰符是java.lang.reflect.Modifier的静态属性。

对应表如下:

PUBLIC: 1

PRIVATE: 2

PROTECTED: 4

STATIC: 8

FINAL: 16

SYNCHRONIZED: 32

VOLATILE: 64

TRANSIENT: 128

NATIVE: 256

INTERFACE: 512

ABSTRACT: 1024

STRICT: 2048

下面获得Person类中的方法

Method m[] = c1.getDeclaredMethods() ; //取得全部方法

for(int i=0;i

Class> r = m[i].getReturnType() ; //得到返回值类型

Class> p[] = m[i].getParameterTypes() ; //取得全部参数的类型

int xx = m[i].getModifiers() ; //得到修饰符

System.out.print(Modifier.toString(xx) + " ") ; //输出修饰符

System.out.print(r + " ") ;

System.out.print(m[i].getName()) ;

System.out.print("(") ;for(int j=0;j

System.out.print(p[j].getName()+ " " + "arg" +j) ;if(j

System.out.print(",") ;

}

}

Class> ex[] = m[i].getExceptionTypes() ; //取出异常

if(ex.length>0){

System.out.print(") throws ") ;

}else{

System.out.print(")") ;

}for(int j=0;j

System.out.print(ex[j].getName()) ;if(j

System.out.print(",") ;

}

}

System.out.println() ;

}

输出为

public classjava.lang.String toString()public classjava.lang.String getName()public voidsetName(java.lang.String arg0)public void setAge(intarg0)public int getAge()

调用Person类中的getName方法为

Method method = null;try{

method= c1.getMethod("getName");try{

Object name=method.invoke(per);

System.out.println(name);

}catch(IllegalAccessException e) {//TODO Auto-generated catch block

e.printStackTrace();

}catch(IllegalArgumentException e) {//TODO Auto-generated catch block

e.printStackTrace();

}catch(InvocationTargetException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}catch(NoSuchMethodException e) {//TODO Auto-generated catch block

e.printStackTrace();

}catch(SecurityException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

调用有参数的方法

Method method = null;try{

method= c1.getMethod("setName",String.class);try{

method.invoke(per,"java-java");

System.out.println(per.getName());

}catch(IllegalAccessException e) {//TODO Auto-generated catch block

e.printStackTrace();

}catch(IllegalArgumentException e) {//TODO Auto-generated catch block

e.printStackTrace();

}catch(InvocationTargetException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}catch(NoSuchMethodException e) {//TODO Auto-generated catch block

e.printStackTrace();

}catch(SecurityException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

今天上午的基本学习到此结束。java文档中,Class类中还有很多方法。后续继续学习。

三、总结

显然学过spring的朋友一定明白了,为什么可以通过配置文件就可以让我们获得指定的方法和变量,在我们创建对象的时候都是通过传进string实现的,就好像你需要什么,我们去为你生产,还有我们一直在用Object,这就说明java语言的动态特性,依赖性大大的降低了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
为了优化这个 SQL 查询,我们可以做以下几点改进: 1. 索引优化:确保 `par_per` 表和 `par_lot` 表的相关字段上都有合适的索引,例如 `par_per.lot_id`、`par_per.space_no`、`par_per.status`、`par_per.is_deleted`,以及 `par_lot.id` 和 `sys_user_par.parking_id`。 2. 子查询优化:将子查询改为连接查询,这样可以避免在 `IN` 子查询使用子查询。 3. 连接条件优化:在 `left join fd_ord fo` 子句,添加条件 `fo.status = 0` 和 `(pp.status = 0 or pp.status = 1)`,以过滤不必要的行。 4. 聚合优化:根据查询需求,确定是否需要对 `pp.space_no` 进行分组和聚合。 改进后的 SQL 查询如下所示: ```sql SELECT pp.id, pp.lot_id, pp.lot_no, pp.measurement, pp.is_long_rent, pp.rent_license_plate, pp.rent_user, pp.rent_start_time, pp.rent_end_time, pp.create_time, pp.create_by, pp.update_time, pp.update_by, pp.is_deleted, pp.per_type, pp.space_no, CASE WHEN fo.order_no IS NOT NULL AND pp.status=1 THEN 1 WHEN fo.order_no IS NOT NULL AND pp.status=0 THEN 2 WHEN pp.status = 2 THEN 3 WHEN fo.order_no IS NULL THEN 0 ELSE pp.status END AS status, fo.license_plate FROM par_per pp LEFT JOIN fd_ord fo ON pp.space_no = fo.space_no AND fo.status = 0 AND (pp.status = 0 OR pp.status = 1) JOIN par_lot pl ON pp.lot_id = pl.id JOIN sys_user_par sup ON pl.id = sup.parking_id AND sup.user_id = 1 WHERE pp.is_deleted = 0 AND (pp.status = 0 OR pp.status = 1) GROUP BY pp.space_no ORDER BY status DESC; ``` 请注意,这只是一种可能的优化方法,具体的优化策略可能需要根据数据库的实际情况和性能测试结果进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值