在正常情况下,需要先有一个类的完整路径引入之后才可以按照固定的格式产生实例话对象,但是在Java中也允许通过一个实例话对象找到一个类的完整信息。那么这就是Class类的功能。

实际上类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即可以通过对象的反射求出类的名称。

实例化Class类,获得字节码文件的方法有三种:

  • 第一种:通过forName()方法;
  • 第二种:类.class
  • 第三种:对象.getClass()

package toto.learn;

class X1{}

publicclass GetClassDemo02 {

publicstaticvoid main(String[] args) {

Class<?> c1=null;//指定泛型

Class<?> c2=null;//指定泛型

Class<?> c3=null;//指定泛型

try{

c1=Class.forName("toto.learn.X");//最常用的形式,这种方式将字节码文件加载到内存中。

}catch(ClassNotFoundException e){

e.printStackTrace();

}

c2 = new X1().getClass();//通过Object类中的方法实例

c3 = X1.class;//通过类class实例化

System.out.println("类名称:"+c1.getName());//得到类的名称

System.out.println("类名称:"+c2.getName());//得到类的名称

System.out.println("类名称:"+c3.getName());//得到类的名称

}

}

通过以上方法获得类名称的方式得到的是包名+类名

如果要想通过Class类本身实例化其他类的对象,则可以使用newInstance()方法,但是必须要保证被实例化的类中必须存在一个无参够造方法

被实例化对象的类中必须存在无参构造方法,如果不存在的话,则肯定是无法实例化的。

1、 通过Class类中的getConstructors()取得本类中的全部构造方法

2、 向构造方法中传递一个对象数组进去,里面包含了构造方法中所需的各个参数

3、 之后通过Constructor实例化对象。

package org.lxh.demo15.instancedemo;

import java.lang.reflect.Constructor;

publicclass InstanceDemo03 {

publicstaticvoid main(String[] args) {

Class<?> c = null;

try {

c = Class.forName("org.lxh.demo15.instancedemo.Person");    // 声明Class对象

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

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

Constructor<?> cons[] = null;   // 声明一个表示构造方法的数组

cons = c.getConstructors();  // 通过反射,取得全部构造

try {// 向构造方法中传递参数,此方法使用可变参数接收,并实例化对象

per = (Person) cons[0].newInstance("李兴华", 30);

} catch (Exception e) { // 因为只有一个构造,所以数组下标为0

e.printStackTrace();

}

System.out.println(per);        // 输出对象

}

}

per = (Person)cons[0].newInstance("李兴华", 30); //此处是调用并使用构造方法的部分。

在声明对象数组的时候,必须考虑到构造方法中参数的类型顺序,所以第一个参数的类型为Stirng,第二个参数的类型WieInteger(在使用是可以自动拆箱)

Constructor<?>cons[]=null;//实例化构造方法的数组

Cons =c.getConstructors();//取得全部构造

//向构造方法中传递参数,此方使用可变参数接收,并实例化对象

Per = (Person)cons[0].newInstance(“李兴华”,30);

设置构造方法的参数内容

publicPerson(String name,int age){//通过构造设置属性内容

}

反射的应用

可以使用反射取得实现的全部接口

可以使用反射取得一个类所继承的父类

可以使用反射取得一个类中的全部构造方法

可以使用反射取得一个类中的全部方法

可以使用反射取得一个类中的全部属性

在实际开发中发,以上的程序就是反射应用最多的地方,当然反射机制所提供的功能远不如此,还可以通过反射得到一个类中的完整构造,那么这就要使用到java.lang.reflect包中的一下几个类。

Constructor:表示类中的构造方法

Field:表示类中的属性

Method:表示类中的方法

这三个类都是AccessibleObject类中的子类。

要想取得一个类中所实现的全部接口,则必须使用Class类中的getInterfaces()方法。此方法定义如下:

publicClass[] getInterfaces();

此方法返回一个Class类的对象数组,之后就可以直接利用Class类中的getName()方法输出即可。

通过反射取得实现的全部接口

package org.lxh.demo15;

publicclass GetInterfaceDemo {

publicstaticvoid main(String[] args) {

Class<?> c1 =null;//声明Class对象

try{

c1 = Class.forName("org.lxh.demo15.Person");//实例化Class对象

}catch(ClassNotFoundException e){

e.printStackTrace();

}

Class<?> c[] = c1.getInterfaces();//取得实现的全部接口

for(int i=0;i<c.length;i++){

System.out.println("实现的接口名称:"+c[i].getName());//输出接口名称

}

}

}

一个类中可以实现多个接口,但是只能继承一个父类,所以如果要想取得一个类的父类,可以直接使用Class类中的getSuperclass()方法。此方法定义如下:

PublicClass<? Super T> getSuperclass()

此方法返回的是Class实例,和之前的得到接口一样,可以通过getName()方法取得名称。

取得构造方法的例子:

package org.lxh.demo15;

import java.lang.reflect.Constructor;//导入反射操作包

publicclass GetConstructorDemo01 {

publicstaticvoid main(String[] args) {

Class<?> c1 = null;//声明Class对象

try{

c1 = Class.forName("org.lxh.demo15.Person");

}catch(ClassNotFoundException e){

e.printStackTrace();

}

Constructor<?> con[]=c1.getConstructors();//得到全部构造方法

for(int i=0;i<con.length;i++){

System.out.println("构造方法:"+con[i]);//直接打印输出

}

}

}

还原修饰符

在整个Java中对于方法的修饰符使用一定的数字表示出来的,而如果要想把这个数字还原成用户可以看懂的关键字,则必须依靠Modifier类完成,此类定义在java.lang.reflect包中。直接使用Modifer类的一下方法可修饰符:

publicstatic String toString(int mod)

int  mo = con[i].getModifiers();

System.out.print(Modifier.toString(mo)+””); //还原权限

getDeclaredMethods()方法,此方法返回一个Method类的对象数组,而如果要想进一步取得方法具体信息,例如:方法的参数,抛出的异常声明等等,则就是必须依靠Method类

再反射操作中同样可以取得一个类中的全部属性,但是在取得属性的时候有以下两种不同的操作:

得到实现的接口或父类中的公共属性:public Field[] getFields() throwsSecurityException

得到本类中自己定义的的全部属性:public Field[] getDeclaredFields() throws SecurityException

如果要使用反射调用类中的方法可以通过Method类完成,操作步骤如下:

1、 通过Class类的getMethod(Stringname,Class…parameterTypes)方法取得一个Method的对象,并设置此方法操作时所需的参数类型。

2、 之后才可以使用invoke进行调用,并向方法中传递要设置的参数。

在Proxy类中的newProxyInstance()方法中,需要一个ClassLoader类的实例,ClassLoader实际上对应的是类加载器,在Java中主要有以下三种类加载器:

BootstrapClassLoader:此加载器采用C++ 编写,一般开发中是看不到的;

ExtensionClassLoader:用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类;

AppClassLoader:加载classpath指定的类,是最常用使用的一种加载器。

通过forName()加载类两次时,此时的类只加载了一次

如果有以下代码:

Object obj= new VipUser();//这里VipUser是User的子类,它继承了User

if(obj instanceof User){

System.out.println("instanceof判断是一个user");

User user = (User)obj;

}

当使用以上代码中的instanceof来判断时,此时obj就是一个User了,但实际上它不是。它只是User的一个子类。

总结:使用instanceof时主要用来判断是否实现了后面的接口。

if(obj.getClass()==User.class){

System.out.println("getClass判断,是一个user");

User user = (User)obj;

}

而getClass()用于判断对象的准确类型。

在后面用到的类:

package toto.learn1;

publicclass User {

private String name;

private String password;

private String gender;

public User(String name, String password, String gender) {

super();

this.name = name;

this.password = password;

this.gender = gender;

}

public User() {

super();

// TODO Auto-generatedconstructor stub

}

public User(String name, String password) {

super();

this.name = name;

this.password = password;

}

public String getName() {

returnname;

}

publicvoid setName(String name) {

this.name = name;

}

public String getPassword() {

returnpassword;

}

publicvoid setPassword(String password) {

this.password = password;

}

public String getGender() {

returngender;

}

publicvoid setGender(String gender) {

this.gender = gender;

}

publicvoid run(String str, int num){

System.out.println("run");

}

publicvoid run(String name){

System.out.println("hello:"+name);

}

}

以下是关于反射的部分。

package toto.learn1;

import java.lang.reflect.Constructor;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

import java.lang.reflect.Modifier;

publicclass Demo2 {

/**

* 反射

* @throwsIllegalAccessException

* @throwsInstantiationException

* @throwsNoSuchMethodException

* @throwsSecurityException

*/

publicstaticvoid main(String[] args) throws Exception {

Class clazz = User.class;

//构造方法

//获得构造方法

Constructor[] cons = clazz.getConstructors();

for(Constructor con : cons){

//参数列表,获得的约定是完整的参数类型,包括这种类型坐在的包。

Class[] types = con.getParameterTypes();

System.out.println("参数类型为:");

for(Class type:types){

System.out.println(type.getName()+"...");

}

System.out.println();

}

//获得指定的构造方法     创建对象

try {

Object obj = clazz.newInstance();//默认调用无参的构造方法

System.out.println(obj.getClass());

} catch (InstantiationException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

}

/**参数类型为:

java.lang.String...

java.lang.String...

参数类型为:

java.lang.String...

java.lang.String...

java.lang.String...

class toto.learn1.User*/

System.out.println("-------------------------");

//获得指定的构造方法2 创建对象

Object obj = clazz.newInstance();//默认调用无参的构造方法

Constructor constructor = clazz.getConstructor(String.class,String.class);//此处调用有两个参数的构造方法

//String.class是因为构造方法中有带有年个参数的构造方法的形参都是String类的。

User usr = (User)constructor.newInstance("toto","查看");//传递两个参数。

System.out.println(usr.getName()+"   "+usr.getPassword());//结果:toto   查看

//方法

//获得类所有的方法

Method [] methods = clazz.getMethods();

for(Method method:methods){

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

}

/**通过getMethods()方法获得的类中包含有父类的方法,并且拿到的是共有的方法

*  run

run

getName

setName

getPassword

setPassword

getGender

setGender

wait

wait

wait

hashCode

getClass

equals

toString

notify

notifyAll

* */

//如果想获得声明的所有方法,包括非public的,不包括继承的,可以使用一下途径实现

System.out.println("-----------------------");

Method [] methods2 = clazz.getDeclaredMethods();

for(Method method:methods2){

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

}

/**结果是:

*  run

run

getName

setName

getPassword

setPassword

getGender

setGender*/

//获得指定的方法,调用方法

Method runMethod = clazz.getMethod("run", String.class); /**第一个表示要调用那个方法

第二个参数是可变参数,表示调用的润方法的参数类型。*/

//获得了方法后,要执行时,得给出一个对象,在这里要执行的对象是User,故作如下实例

User usr1 = new User();

runMethod.invoke(usr1, "toto");//表示执行usr1对象中的runMethod方法,并且向方法中传递了参数。

/**

* 运行结果:hello:toto 此为User类中run(String name);方法输出的结果,其中name即为toto*/

//属性

//获得对象的属性,先创建一个对象

Object object = new User("toto","123","male");//调用User中的构造方法:

//由于获得对象的私有属性,得获得get方法,故得先获得对象的字节码文件,通过这个文件获得get方法

Class objectClazz = object.getClass();

//获得get方法

Method runMethod2 = clazz.getMethod("getName"); //由于该方法没有参数,故不用在向里面传递参数

//执行此方法,输出参数

Object name = runMethod2.invoke(object);

System.out.println(name);//由于上面传递了name值,故此处返回的结果值为:toto

//获得所有属性

System.out.println("-------------------------------");

//Field[] fields =clazz.getFields();//此方法拿到的是public的属性,由于User类中没有共有的属性

Field[] fields = clazz.getDeclaredFields();//拿到声明的属性

for(Field fd : fields){

System.out.println(fd.getName()+"属性类型: "+fd.getType());

}

/** 结果为:

*  name属性类型: class java.lang.String

password属性类型: class java.lang.String

gender属性类型: class java.lang.String*/

//为对象的password属性赋值:

User user2 = new User();

String fieldName = "password";//作为变量来处理的,可以传递任意的属性名称

//getpw是通过反射拿到的属性,其实就是password

Field getpw = user2.getClass().getDeclaredField(fieldName);

//判断属性是否为私有:

int num = getpw.getModifiers();//返回的是整型的值。

if(num == Modifier.PRIVATE){//获得的是

System.out.println("属性是私有的");

//让java虚拟机不检查访问权限

//getpw.setAccessible(true);

}

//System.out.println(getpw);//结果private java.lang.Stringtoto.learn1.User.password

getpw.set(user2, 234567);//前一个参数表示的是为那个对象赋密码。

System.out.println(user2.getPassword());

}

}

l 通过Field类访问对象属性时,需要注意访问权限的问题,若对象

的属性被声明为私有,则无法访问,此时需要打开java语言检查

filed.setAccessible(true);

Method类代表某个类中的一个成员方法

l 通过invoke方法可以调用Method表示的方法,此时同样需要传递

对象给Method,若被调用的方法为静态,则传入一个null值

l 注意:jdk1.4和jdk1.5的invoke方法的区别:

l Jdk1.5:public Object invoke(Objectobj,Object... args)

l Jdk1.4:public Object invoke(Objectobj,Object[] args)

l 当传入一个数组时,为了向后兼容,虚拟机会优先考虑考虑

调用JDK1.4的方法

Java中的反射的应用相关推荐

  1. 浅说Java中的反射机制(一)

    在学习传智播客李勇老师的JDBC系列时,会出现反射的概念,由于又是第一次见,不免感到陌生.所以再次在博客园找到一篇文章,先记录如下: 引用自java中的反射机制,作者bingoideas.(()为我手 ...

  2. Java 中使用反射来创建对象、调用方法

    Java 中使用反射来创建对象.调用方法 反射创建对象 反射调用方法 反射调用私有方法 反射调用可变参私有方法 反射调用的方法自身可以抛出异常的情形   假设已有下面的类: import java.l ...

  3. java代码安全检测机制_全面解析:java中的反射机制,内含代码验证解析

    什么是反射? 在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功 ...

  4. 深入理解Java中的反射技术

    Java中的反射机制是指在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法:并且对于任意一个对象,都能够调用它的任意一个方法:这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射 ...

  5. formdata 接受参数中带有class 对象_浅析JAVA中的反射机制及对Servlet的优化

    今天来聊聊java中的反射机制,工作以后发现很多东西动不动就要使用反射或者动态代理,如果不能很好的理解反射,那么对于动态代理等一些重要的设计模式就会有种不够通透的感觉. 所谓的反射,就是在运行状态中, ...

  6. java中的反射机制是什么

    给大家介绍一下java中的反射机制,java中反射机制更体现出了java的灵活性.多态.和类之间的耦合性. 1:反射是一种间接操作目标对象的机制,只要给定类的名字,就可以通过反设机制获取所有的类信息. ...

  7. Java中的反射和枚举

    假设现在上面的数据是以二次探测的方式来进行存放的,现在让你求: 现在找1:直接就能找到----->次数是1 现在找4:直接就可以找到---->次数是1 现在找14:先得到4的下标,发现不是 ...

  8. Java中的反射机制详讲

    Java中的反射机制详讲 1.反射机制_介绍_Class对象获取 2.反射机制_动态操作_构造器_方法_属性 3.动态编译_DanamicCompile_反射调用main方法问题 好文推荐:排序.查找 ...

  9. Java中的反射如何理解——精简

    目录 引言 反射概念 反射获取类对象 反射获取构造器对象 获取构造器对象并使用 反射获取成员变量对象 反射获取方法对象 反射获取成员方法并使用 引言 经过前面的学习,相信大家已经能够对网络编程有了一定 ...

  10. 什么是java中的反射?反射的一些常用方法

    一.什么是java中的反射 Java 反射,就是在运行状态中. 获取任意类的名称.package信息.所有属性.方法.注解.类型.类加载器等 获取任意对象的属性,并且能改变对象的属性 调用任意对象的方 ...

最新文章

  1. 此三层非彼三层——MVCamp;UBD
  2. python datetime timedelta函数_Python Pandas DatetimeIndex.to_perioddelta()用法及代码示例
  3. 30.jvm.gc(GC之详解CMS收集过程和日志分析)
  4. PHP占用内存越来越多,解决phpQuery占用内存过多的问题
  5. 终于有人把YOLO讲明白了
  6. centos7进入单用户模式
  7. 从数据库中导出数据库文档(新增了索引及表的描述信息)
  8. the first blog
  9. 不同语言实现两个变量的交换 Python之禅
  10. 联想m5服务器管理网口装系统,联想/IBMx3650M5服务器引导系统安装方法
  11. 必看 | 机器视觉基础入门
  12. 多测师杭州拱墅校区__肖sir__软件测试生命周期(4)
  13. 什么是Google AMP
  14. unity ar vr_学习在Unity中创建AR和VR应用
  15. HDLC概述-iealb
  16. NMS(非极大值抑制)的来龙去脉,简单明了
  17. 阿里天池二手车交易价格预测(一)——EDA
  18. 自然生长不含咖啡碱的茶树新品种--T三有机可可茶
  19. uniapp爱玩小灰视频播放器使用流程
  20. 剑网3虚拟机,总是登不上,提示无法连接服务器。。。愁死了?

热门文章

  1. boost::tokenizer模块相关的测试程序
  2. boost::math模块使用 Brent 方法求函数最小值的示例
  3. hana::detail::variadic::at用法的测试程序
  4. boost::gil::generate_gaussian_kernel用法的测试程序
  5. boost::fibers::shared_future的用法实例
  6. ITK:形态分水岭MorphologicalWatershed分割
  7. ITK:Sobel边缘检测图像滤镜
  8. DCMTK:比较DICOM图像并计算差异指标
  9. VTK:可视化之Kitchen
  10. OpenCV GrabCut分割的实例(附完整代码)