一、类对象与反射

先来简单介绍一下反射,反射使得程序员能够更加的了解一个类,包括获得构造方法、成员方法、成员域包括注解等。

1.访问构造方法

访问构造方法有四种方式,

getDeclaredConstructors(); 获取所有构造函数,包括public、private等等

getDeclaredConstructor( Class parameterTypes); 获取相应参数类型的构造方法

getConstructors(); 获取所有公有public修饰的构造方法

getConstructor(Class parameterTypes);  获取相应参数类型的公有构造方法

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier; public class Ref {
private int i;
private String s;
public Ref(String s1)
{
s=s1;
}
public Ref(int i)
{
this.i=i;
}
Ref()
{
i=0;
s="null";
}
private Ref(int i1,String s2)
{
i=i1;
s=s2;
} public void getString()
{
System.out.println(s);
} public static void main(String []args)
{
Class re=Ref.class;
try { //Constructors
Constructor [] c= re.getDeclaredConstructors();// 所有构造方法
for(Constructor con:c)
System.out.println(con);
System.out.println("-----------------------------------------");
Constructor [] c0= re.getConstructors();// 所有公有构造方法
for(Constructor con:c0)
System.out.println(con);
System.out.println("-----------------------------------------");
System.out.println(re.getConstructor(int.class));// 所有公有参数为int的构造方法
System.out.println("-----------------------------------------");
System.out.println(re.getDeclaredConstructor(int.class));// 参数为int的构造方法
Constructor X=re.getDeclaredConstructor(int.class,String.class);// 参数为int和String的构造方法 System.out.println(X.getName());
System.out.println(X.isAccessible());
System.out.println(X.isVarArgs());
int mo= X.getModifiers();
System.out.println(Modifier.isStatic(mo)); } catch (Exception e) {
e.printStackTrace();
}
}

注意参数parameter的形式,应写为int.class或者String.class等。上述方法返回的类型均为Constructor对象,当然它可以直接打印,但是它还有一些其他有趣的方法,getName()直接返回构造函数的名称,而getModifiers()方法返回一个int类型的值,可以用来判断是否含有某个关键字,主要方法如下:

此外,除了getModifiers()和getName()之外,还有几个不是很重要的Constructor类的方法想在这里展示一下,首先是newInstance()和isAccessible()和setAccessible():

            Constructor N=re.getDeclaredConstructor(int.class);// 参数为int的构造方法
Constructor X=re.getDeclaredConstructor(int.class,String.class);// 参数为int和String的构造方法
System.out.println(N.isAccessible());
System.out.println(X.isAccessible());
Ref r1= (Ref)N.newInstance(5);
Ref r2= (Ref)X.newInstance(5,"XX");
r1.getString();
r2.getString();

这地方很诡异,一般的逻辑是通过isAccessible()判断是否能够通过newInstance()申请新的实例对象,如果是true的话可以,false应该是不可以,然后通过setAccessible(true)设置完后就可以了,但是上面的例子不管是public还是private都是false,然后竟然还可以使用newInstance(),惊了。其实newInstance()和new一个对象应该是差不多的,参数类型和个数一定要对上,否则抛异常。所以这里是有一点叉子的,不知道哪里出了问题。

接下来是getParameterTypes()和getExceptionTypes()。

    private Ref(int o,String ss) throws IOException,NoSuchMethodException  //增加异常
{
i=o;
s=ss;
} /*Constructor - isVarArgs() getParameterTypes() and getExceptionTypes()*/ // System.out.println(X.isVarArgs()); Class [] p = X.getParameterTypes();
Class [] e = X.getExceptionTypes();
for (Class x:p)
System.out.println(x);
for (Class x:e)
System.out.println(x);

结果一目了然可以看出这两个方法是做什么的,不再多说了。

2.访问普通方法和域

实际上,访问方法和域与构造方法十分类似,均是有四种方法,名称也是相似,只不过有getConstructors()等改为getFileds()等和getMethods()等,只不过获取特定对象的参数不同,例如构造函数是要指定参数类型和个数如int.class,但是域是指定名称,方法是指定名称+参数:

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier; public class Ref {
private int i;
private String s;
public static double d; public void getString()
{
System.out.println(i+" "+s);
}
public void getString(int j){System.out.println(i+" "+j+" "+s);} public static void main(String []args)
{
Class re=Ref.class;
try { //methods or fields
System.out.println("-----------------------------------------");
Field [] f= re.getDeclaredFields();
for(Field fi:f)
System.out.println(fi);
Field f1 = re.getDeclaredField("d");
System.out.println(f1);
System.out.println("-----------------------------------------");
Method[] m= re.getDeclaredMethods();
for(Method me:m)
{
int mom= me.getModifiers();
System.out.println(Modifier.toString(mom)); }
Method m1 = re.getMethod("getString",int.class);
System.out.println(m1);
Method m2 = re.getMethod("getString");
System.out.println(m2); } catch (Exception e) {
e.printStackTrace();
}
}
}

结果与预期一致。

对于方法来说,除了getName()、getParameterTypes()和getExceptionTypes()以及getModifiiers()与构造方法使用方法完全一致,还有getReturnType()和invoke()函数值得一看,其实只看名字就知道是干嘛的了,没错就获得返回值类型和直接调用该方法:

            /*Method - invoke() and getReturnType*/

            Ref rm = new Ref();
m1.invoke(rm,15);
Class r = m2.getReturnType();
System.out.println(r);

需要新实例化一个对象,然后成为invoke的方法的参数(即rm)才能调用......

对于域来说,除了getName()、getModifiers(),还有set()和get()

            Ref rm = new Ref();
Field f1 = re.getDeclaredField("d");
System.out.println(f1); Field f2 = re.getDeclaredField("s");
System.out.println(f2); System.out.println("the former value of d is "+f1.get(rm));
System.out.println("the former value of s is "+f2.get(rm)); f1.set(rm,5.5);
f2.set(rm,"newer"); System.out.println("the latter value of d is "+f1.get(rm));
System.out.println("the latter value of s is "+f2.get(rm));

其实除此之外还是有setInt()、getInt()、setFloat()、setBoolean()、getFloat()、getBoolean()方法,但是使用起来并不像set()和get()方法简便,只需要注意类型的转换即可,例如上述代码中f1.set(rm,5.5)可以改成set(rm,5)也是可以的,因为int类型转化为double型没问题。然而使用setInt()时,后面的值类型必须为整型,同样的getInt()也要求该域的类型为整型或者能直接转化为整型的,例如

            Field f3 = re.getDeclaredField("i");
System.out.println(f3);
System.out.println("the latter value of d is "+f3.getDouble(rm));

运行没有问题,即使i是整型,也能获得其double型,因为整型可以直接转化为双浮点型。

但是:

            f3.setFloat(rm,5.5f);
System.out.println("the latter value of d is "+f3.get(rm));

将整型成员域设置为float那是不行的,因为float不能直接转化为整型,会有信息损失。结果就是抛出IlleagalArgumentException:

3.获得该类其他信息

比如获得类的包getPackage(),类的名称getName(),继承的类getSuperclass()和实现的所有接口getInterfaces(),除了因为类可以实现多个接口,因此返回的是Class数组,其他都是返回的一个对象,可以直接打印。

            System.out.println(re.getPackage());
System.out.println(re.getName());
System.out.println(re.getSuperclass());

结果:

null
Ref
class java.lang.Object

除了包名的结果有些意外,竟然是null,不过确实使用IDEA的过程中没有建包的过程,第一句也不是package XX,我以为是简化了,没想到是真没有,估计用Eclipse肯定是有的。再来因为本实例中的类没有继承任何类,所以获得超类直接返回Object类。至于获得接口数组可以参考之前遍历所有方法(或域)的步骤,一个foreach就可以了。

好了,反射就到此为止,希望这周能把注解搞完!下期注解。

Java类的反射的更多相关文章

  1. java--分析简单java类与反射的联系

    分析简单java类与反射的联系 web对反射的操作支持 在JSP之中有一种技术--javaBean.而且在jsp里面也配套有相应的操作方式,javaBean的核心在于简单java类,于是下面演示此操作 ...

  2. java类的反射机制

    1.获得一个类的类对象有哪些方式? - 方法1:类型.class,例如:String.class- 方法2:对象.getClass(),例如:"hello".getClass()- ...

  3. Java 类反射机制分析

    Java 类反射机制分析 一.反射的概念及在Java中的类反射 反射主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.在计算机科学领域,反射是一类应用,它们能够自描述和自控制.这类应用通过某 ...

  4. JAVA异常处理、常用类、反射、集合

    异常 异常:在Java中是指被一个方法抛出的对象. 分类:检查异常.运行时异常.错误 运行时异常(uncheckd):RuntimeException和其子类 检查异常(checkd/搜检异常):指E ...

  5. JAVA进阶之旅(二)——认识Class类,反射的概念,Constructor,Field,Method,反射Main方法,数组的反射和实践

    JAVA进阶之旅(二)--认识Class类,反射的概念,Constructor,Field,Method,反射Main方法,数组的反射和实践 我们继续聊JAVA,这次比较有意思,那就是反射了 一.认识 ...

  6. java中使用反射获取pojo(实体)类的全部字段值

    说起反射.不得不说它实在是太强大了,通过反射就能够轻轻松松拿到各种东东,假设你想在项目中解除对某个类的依赖,能够考虑用反射. 今天跟大家分享的是通过java中的反射,获取pojo类的全部字段值. 为什 ...

  7. Java常用类及反射,类加载

    1.系统相关类 Java提供了System类和Runtime类来与程序运行的平台进行交互 A.System类代表当前Java程序的运行平台 a. System类是一个final类,该类的所有属性和方法 ...

  8. 如何利用缓存机制实现JAVA类反射性能提升30倍

    一次性能提高30倍的JAVA类反射性能优化实践 文章来源:宜信技术学院 & 宜信支付结算团队技术分享第4期-支付结算部支付研发团队高级工程师陶红<JAVA类反射技术&优化> ...

  9. java 中利用反射机制获取和设置实体类的属性值

    摘要: 在java编程中,我们经常不知道传入自己方法中的实体类中到底有哪些方法,或者,我们需要根据用户传入的不同的属性来给对象设置不同的属性值,那么,java自带的反射机制可以很方便的达到这种目的,同 ...

随机推荐

  1. 【图像处理】H.264有四种画质级别

    H.264有四种画质级别,分别是BP.EP.MP.HP,想要说明H.264 HP与H.264 MP的区别就要讲到H.264的技术发展了 H.264 视频编码技术在视频采集.后期制作等网络视频服务领域的 ...

  2. SpringBoot消息队列之-rabbitMQ

    一.概述 1.在大多应用中,我们系统之间需要进行异步通信,即异步消息. 2.异步消息中两个重要概念:消息代理(message broker)和目的地(destination) 当消息发送者发送消息以后 ...

  3. [转帖]nginx 80端口重定向 转发到443端口

    nginx 80端口重定向到443端口 2017年05月16日 13:53:58 幸福丶如此 阅读数 33387   版权声明:本文为博主原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文 ...

  4. python列表与字符串、元组的区别以及列表引用的方式

    一.字符串 字符串也可以用下标取值.切片.for循环.len()取长度以及 in 和 not in 来进行操作. 但字符串是不可变的,不能被更改.只能构造一个“新的”字符串来存取你想要修改后的数据. ...

  5. kettle 创建作业发送邮件

    1.创建作业 . 2. 发送邮件配置,测试邮件 发件地址可以使用的QQ.126.163等邮箱 smtp server的填写smtp.qq.com或者smtp.126.com等等都可以这里我用Q163邮 ...

  6. Nginx的一些常用配置

    #定义Nginx运行的用户和用户组 #user nobody; #nginx进程数,建议设置为等于CPU总核心数. worker_processes 1; #全局错误日志定义类型,[ debug | ...

  7. @click.prevent.self和@click.self.prevent区别

    注意:prevent 阻止的是“跳转事件”而不是“弹出警告” v-on:click.prevent.self的demo如下: <div id="box"> <di ...

  8. 小a的强迫症 题解

    题面: 小a是一名强迫症患者,现在他要给一群带颜色的珠子排成一列,现在有N种颜色,其中第i种颜色的柱子有num(i)个.要求排列中第i种颜色珠子的最后一个珠子,一定要排在第i+1种颜色的最后一个珠子之 ...

  9. django进阶版1

    目录 字段中choice参数 MTV与MVC模型 AJAX(*********) Ajax普通请求 Ajax传json格式化数据 Ajax传文件 序列化组件 Ajax+sweetalert 字段中ch ...

  10. Codeforces 1244G. Running in Pairs

    传送门 首先对于两个排列 $A,B$ 我们可以把 $A$ 从小到大排序并把 $B$ 重新和 $A$ 一一对应 显然这样不会影响 $\sum_{i=1}^{n}max(A_i,B_i)$ 的值 所以直接 ...