Java中的反射的应用

  在正常情况下,需要先有一个类的完整路径引入之后才可以按照固定的格式产生实例话对象,但是在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(在使用是可以自动拆箱)

  Constructorcons[]=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

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

  }

  }

  }

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

  PublicClass 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

  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:用来进行扩展类的加载,一般对应的是jrelibext目录中的类;

  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);

  l 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的方法

时间: 2024-11-03 18:24:30

Java中的反射的应用的相关文章

Java中的反射机制

反射,reflection,听其名就像照镜子一样,可以看见自己也可以看见别人的每一部分.在java语言中这 是一个很重要的特性.下面是来自sun公司官网关于反射的介绍: Reflection is a feature in the Java programming language. It allows an executing Java program to examine or "introspect" upon itself, and manipulate internal pr

java笔记十:java中的反射

Java中,反射是一种强大的工具.它使您能够创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代表链接.反射允许我们在编写与执行时,使我们的程序代码能够接入装载到JVM中的类的内部信息,而不是源代码中选定的类协作的代码.这使反射成为构建灵活的应用的主要工具.但需注意的是:如果使用不当,反射的成本很高. Java的类反射所需要的类并不多,它们分别是:Field.Constructor.Method.Class.Object,下面我将对这些类做一个简单的说明.Field类:提供有关类或接

java中的反射的变量定义问题

问题描述 java中的反射的变量定义问题 新人初学,还望各位能多多帮助 我在学习反射的过程中,遇到这样一个问题 String s1 = new String (new StringBuffer("abc")); 这条语句我看了下JDK文档,发现String的构造函数中有一个构造方法的参数是StringBuffer的对象,然后又看了看StringBuffer的定义,发现这条语句等于 String s1 = "abc"; 为什么要这样写呢, 还有 Constructor

java中使用反射获取pojo(实体)类的所有字段值

       说起反射,不得不说它实在是太强大了,通过反射就可以轻轻松松拿到各种东东,如果你想在项目中解除对某个类的依赖,可以考虑用反射.        今天跟大家分享的是通过java中的反射,获取pojo类的所有字段值.        为什么要做这个操作的呢?主要是为了重写实体类的toString方法.有人会说,直接重写toString方法,返回字段.toString()的字符串不就行了.这么做的确可以,但是如果你的pojo类有上百个,上千个,你还要一个一个改吗?所以我们需要从新的方向去解决.

java-早绑定是不是Java中的反射的运行原理啊?

问题描述 早绑定是不是Java中的反射的运行原理啊? 解决方案 恰恰相反,反射的原理和运行时绑定类似,在运行时检索程序的元信息(metadata),其中包含类型.成员等等,然后动态调用. 解决方案二: Java 运行原理JAVA运行原理Java的运行原理

java中利用反射调用另一类的private方法的简单实例_java

我们知道,Java应用程序不能访问持久化类的private方法,但Hibernate没有这个限制,它能够访问各种级别的方法,如private, default, protected, public. Hibernate是如何实现该功能的呢?答案是利用JAVA的反射机制,如下:  import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class ReflectDemo

java 中的反射API 暑假第十天

 java 中的反射API   反射API 当我们在开发Debugger的时候用到  反射API可以获得一个类的内部构造  定义的成员 方法 构造函数 ... java.lang.reflect.*  必须导入因为java.lang会自动导入但是 子包却不会    这个包中有一堆类  如 Method  Field  Construction类 等等 java.lang.Class  中的函数可以获得 这些类的数组  例如getDeclaredFields() 返回声明的 所有 变量的一个Fie

根据实例详解Java中的反射机制

概念:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制.作用:Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类:在运行时构造任意一个类的对象:在运行时判断任意一个类所具有的成员变量和方法:在运行时调用任意一个对象的方法:生成动态代理. 可以说Java的反射机制是Java中所有框架的基础,要对SSH等框架有一个深刻的理解

浅析Java中的反射机制原理

       反射反射,程序员的快乐!        Java中反射机制使用的还是比较广泛的,系统的灵活性.可扩展性大都都是通过反射等方式来加载外部插件,使得系统与插件解耦的同时,增加了功能.但是很多人都只是会用,却是不知道它的实现机制,今天就由我来带大家揭开反射机制的神秘面纱.        Java中是用Class.forName(classname)来反射类. package com.java.reflecttest; import com.java.dbtest.DBTest; /**