老生常谈Java反射机制(必看篇)

什么是反射机制

反射是java语言的一个特性,它允程序在运行时(注意不是编译的时候)来进行自我检查并且对内部的成员进行操作。例如它允许一个java的类获取他所有的成员变量和方法并且显示出来。这个能特定我们不常看到,但是在其他的比如C或者C++语言中很不就存在这个特性。一个常见的例子是在JavaBean中,一些组件可以通过一个构造器来操作。这个构造器就是用的反射在动态加载的时候来获取的java中类的属性的。

主要的类

Class 类的实例表示正在运行的 Java 应用程序中的类和接口。Class没有公共的构造方法,Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的

Constructor 提供关于类的单个构造方法的信息以及对它的访问权限(主要提供的是对构造方法使用)

Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)

Field 主要提供对类中的成员变量的访问和使用

Class

Class类也使用了泛型,即是Class

常用的方法

getConstructor(Class[] params) 获取公共的(public)的构造方法,并且限定其中的参数个数和类型可以获得不同的公共构造方法

Constructor[] getConstructors() 返回所有的公共(public)的构造方法

getDeclaredConstructor(Class[] params) 获取所有指定的构造方法,但是需要注意的是当获取私有的构造方法的时候需要使用setAccessible设置访问权限为true才能进行构造,否则出现异常

Constructor[] getDeclaredConstructors() 返所有的构造方法包括public和private,protected修饰的

T newInstance() 返回的是一个调用默认的构造方法(public class_name())实例化的一个Object对象,如果使用泛型那么就返回T类型的,反之返回的是Object需要强制转换才能使用这个对象调用成员函数和成员变量

Class forName(String class_name) 返回class对象,每一个对都有一个方象法返回Class对象(test.class)

Package getPackage() 返回此类所在的包名(package demo) 当然也可以使用Package.getName()获得包的名字(demo)比如constructor.getPackage().getName()

int getModifiers() 返回的是类的修饰符的整数 类型(修饰符的类型有public private protected)其中得到整数可以使用Modifier中toString(int num)得到public,private,protected的类型,比如Modifier.toString(class1.getModifiers())

*Method getMethod(String name, Class<?>... parameterTypes) 返回指定参数的方法Method对象,注意这里仅仅是返回的时公共的方法(public) 比如:Method method=class1.getMethod("display",new Class[]{int.class})这里的display是方法的名字,有一个参数,类型为int

Method[] getMethods() 获取所有的公共的方法(public)返回的是一个数组(Method)

Method getDeclaredMethod(String name,Class<?>... parameterTypes)返回所有的指定的参数的方法(public,private,protected,但是不包括继承的),其中参数可以为null(无参数)

Method[] getDeclaredMethods() 获取所有的方法

Field getField(String name) 指定名字的公共成员变量(public)

Field[] getFields() 获取所有的公共的成员变量

Field getDeclaredField(String name) 获取所有的指定名称的成员变量(public,protected,private),同样在调用私有成员变量的时候需要先设置访问的权限,field.setAccessible(true)

Field[] getDeclaredFields() 获取所有的成员变量(public,protected,private)

getSuperclass() 返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。

URL getResource(String name) 查找指定名称的资源(图片,文件...)注意这个资源一定要和指定类在一个包中,否则返回null,比如查找Test类下的airplane.png图片:Test.class.getResource("airplane.png")这里返回的将是绝对路径

获取Class的对象并且实例化

使用Class.forName(String className) 其中className一定是包含包的名字,下面的demo就是包的名字,Test是类的名字。这是最常用的方法,学过JDBC的都知道加载驱动的时候就是使用的Class.forName()

 /*
   * 第一种使用forName(String className),其中className一定是包含包的名字,下面的demo就是包的名字,Test是类的名字
   */
  Class cls=Class.forName("demo.Test");
  Test test=(Test)cls.newInstance();  //这里只是使用了默认的构造方法实例化对象

使用类名.class

  Class cls=Test.class;

使用对象.getClass()

  Test test=new Test();
  Class cls=test.getClass(); 

Constructor

主要是用来对类的构造方法进行操作的,可以看出这个也使用了泛型,和上面的Class是一样的,注意这里如果没有使用泛型,那么原本放回T类型的现在都是返回Object

常用的方法

T newInstance(Object parms) 使用带有参数的构造方法实例化对象,如果使用了泛型,那么返回的就是T类型的,反之返回的是Object类型的,需要强制转换

getName() 以字符串的形式返回构造方法的名称,具体的路径包含包名(demo.Test)

int getModifiers() 和Class类中的方法一样

Method

主要提供的是对类中的方法的操作

常用的方法

Object invoke(Object obj,object args) 使用得到的Method对象调用方法,obj是类的已经构造好的对象,如果是静态方法直接写null,因为静态方法的调用不需要对象,返回值是Object类型的,如果接受返回值,需要使用强制转换成相应的类型,args是传入的参数,如果有多个参数,那么可以直接在后面用逗号添加或者直接创建数组new Object[]{22,"chenjiabing"}比如:method.invoke(test,22,"chenjiabing") method.invoke(test,new Object[]{22,"chenjiabing"})注意:如果调用的private类型的方法,那么需要在前面设置访问的权限,method.setAccessible(true)

String getName() 返回此方法的名字(display)

Modifier getModifiers() 返回此方法的修饰符的类型表示的整数(public,private...),可以使用Modifier.toString()转换成字符串形式

Class getReturnType() 返回这个方法的返回类型

String toString() 返回这个方法表示的字符串的形式

Field

主要提供对类的成员变量的操作

常用方法

String getName() 返回变量名字

Object get(Object obj) 返回此变量在指定对象中的值,因为在构造对象的时候每一个传入的变量的值都不一样,因此需要使用对象obj。obj表示传入的对象,返回的Object类型,因此需要强制转换

void set(Object obj,Object value) 改变obj对象上的变量的值为value

Modifier getModifiers() 返回整数表示修饰的类型

String getType() 获取变量的类型(int,String,double float.....)

Modifier

Modifier 类提供了 static 方法和常量,对类和成员访问修饰符进行解码。修饰符集被表示为整数,用不同的位位置 (bit position) 表示不同的修饰符。

常用的方法

static String toString(int mode) 将代表修饰符的整数形式转换为字符串形式的修饰符,比如将1转换成public

static isInterface(int mode) 如果整数参数包括 interface 修饰符,则返回 true,否则返回 false

static isStatic(int mode)

static isPrivate(int mode)

static isPublic(int mode)

static isAbstract(int mode)

实例

Modifier.toString(Test.class.getModifiers())  //得到Test类的修饰符

使用

有了上面的铺垫,我们就可以使用上面的这些类进行操作了,在进行操作之前,我们需要先定义一个类Test,放在demo包下,内容如下

package demo;

import java.util.jar.Attributes.Name;

import javax.print.attribute.standard.MediaSize.NA;

public class Test {
 public String name;
 private int age;

 public Test() {
  this.name = "陈加兵";
  this.age = 23;
 }

 public Test(String name, int age) {
  this.name = name;
  this.age = age;
 }

 public void display() {
  System.out.println("name=" + this.name + "----age=" + this.age);
 }

 public void set(String name, int age) {
  this.name = name;
  this.age = age;
 }

 private int getAge() {
  return this.age;
 }

}

实例化对象

使用Class默认的构造newInstance()

Class class1=Class.forName("demo.Test"); //静态加载Class

Test test=(Test)class1.newInstance(); //调用默认的构造方法(public Test())实例化对象,由于没有使用泛型,因此需要强转

test.display();  //调用display方法

使用Class中的getConstructor()方法构造对象,需要注意的使用private类型构造方法时一定要先设置访问权限为true-constructor.setAccessible(true);

 /*
   *调用public Test(String name,int age)得到Constructor的两种形式
   * 1.Constructor constructor=class1.getConstructor(new Class[]{String.class,int.class});
   * 2.Constructor constructor=class1.getConstructor(String.class,int.class);这个和上面的是一样的,就是使用的参数形式不一样
   *
   *
   *
   *
   *使用newInstance()构造对象的两种方式
   * 1.Test test=(Test)constructor.newInstance(new Object[]{"chenjiabing",22});
   * 2.Test test=(Test)constructor.newInstance("chenjiabing",22); 只是形式不同而已,不过我还是喜欢上面的形式
   *
   */

  /*
   * 调用public Test(String name,int age)
   *  Class.getConstructor()得到的是公共的构造方法,如果有私有的构造方法,那么就会报错,这时就要使用getDeclaredConstructor(Class<?>... parameterTypes)
   *  Test test=(Test)constructor.newInstance("陈加兵",22);
   *
   *
   * 调用public Test()
   *  Constructor constructor=class1.getConstructor(null);
   *  Test test=(Test)constructor.newInstance(null);
   *
   *
   * 调用private Test(int age)
   *  Constructor constructor=class1.getDeclaredConstructor(new Class[]{int.class});
    constructor.setAccessible(true); //因为private类型是不可以直接访问的,因此需要设置访问权限为true
    Test test=(Test)constructor.newInstance(new Object[]{1000});
  */

  Class class1=Class.forName("demo.Test");
  //访问public Test(String name,int age)
//  Constructor constructor=class1.getConstructor(new Class[]{String.class,int.class});
//  Test test=(Test)constructor.newInstance("陈加兵",22);

  //访问默认的构造方法
//  Constructor constructor=class1.getConstructor(null);
//  Test test=(Test)constructor.newInstance(null);

  //访问private类型的构造方法
  Constructor constructor=class1.getDeclaredConstructor(new Class[]{int.class});
  constructor.setAccessible(true);
  Test test=(Test)constructor.newInstance(new Object[]{1000});
  test.display();

成员方法的操作

使用Class.getMethod()和Class.getDeclaredMethod()方法获取方法,这两个方法的区别前面已经说过了,注意的是调用私有成员方法的之前一定要设置访问权限(method.setAccessible(true))

Method类中的其他方法前面也已经说过了,详细使用请自己尝试

/*
   * 获取Method对象的两种方式:
   *  1.Method method_set=class1.getMethod("set", new Class[]{String.class,int.class});
   *  2.Method method_set=class1.getMethod("set", String.class,int.class);
   *
   *
   * 使用Method.invoke()调用方法的两种方式
   *  1.Object o=method_set.invoke(test, new Object[]{"陈加兵",200});
   *  2.Object object=method_set.invoke(test, "陈加兵",2000);
   */

  /*
   * 获取公共方法(public):
   *  1.Method method=class1.getMethod("display",null); //public void display()
   *  2.Method method_set=class1.getMethod("set", new Class[]{String.class,int.class}); //获取public void set(String name,int age)
   *
   *
   * 获取私有方法(private,protected)
   *  1.Method method_getAge=class1.getDeclaredMethod("getAge", null);
   */

  //使用构造方法构造一个Test对象
  Class class1 =Class.forName("demo.Test");
  Constructor<Test> constructor=class1.getDeclaredConstructor(new Class[]{String.class,int.class});
  Test test=constructor.newInstance(new Object[]{"陈加兵",22});

  Method method=class1.getMethod("display",null); //获取public void display()方法的Method对象
  Object obj=method.invoke(test, null); //调用方法display

  //获取public void set(String name,int age)
//  Method method_set=class1.getMethod("set", new Class[]{String.class,int.class});
  Method method_set=class1.getMethod("set", String.class,int.class);

//  Object o=method_set.invoke(test, new Object[]{"陈加兵",200});
  Object object=method_set.invoke(test, "陈加兵",2000);
  test.display();

  //获取私有方法private int getAge()
  Method method_getAge=class1.getDeclaredMethod("getAge", null);
  method_getAge.setAccessible(true); //必须设置访问权限为true
  //判断返回值类型是否为int类型的
  if("int".equals(method_getAge.getReturnType().toString()))
  {
   int ReturnData=(int) method_getAge.invoke(test, null); //调用并且获取返回值
   System.out.println(ReturnData);
  }
  

成员变量的操作

主要使用的Field类,前面已经详细的说过了

/*
   * 获取public修饰的成员变量:
   *  1.Field field=class1.getField("name"); //获取public的成员变量name的Filed对象
   *
   * 获取private,protected修饰的成员变量:
   *  1. Field field2=class1.getDeclaredField("age");
   */

  Class class1=Class.forName("demo.Test");
  Test test=new Test("陈加兵",1000);
  Field field=class1.getField("name"); //获取public的成员变量name的Filed对象
  System.out.println(field.get(test)); //获得test对象中的name属性的值

  //获取private int age的Field对象
  Field field2=class1.getDeclaredField("age");
  field2.setAccessible(true); //设置访问权限
  System.out.println(field2.get(test));

以上这篇老生常谈Java反射机制(必看篇)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • java 利用java反射机制动态加载类的简单实现

    如下所示: ////////////////// Load.java package org.bromon.reflect; import java.util.ArrayList; import java.util.List; public class Load implements Operator { @Override public List<?> act(List<?> params) { // TODO Auto-generated method stub List<

  • 详解java中反射机制(含数组参数)

    详解java中反射机制(含数组参数) java的反射是我一直非常喜欢的地方,因为有了这个,可以让程序的灵活性大大的增加,同时通用性也提高了很多.反射原理什么的,我就不想做过大介绍了,网上一搜,就一大把.(下面我是只附录介绍下) Reflection 是Java被视为动态(或准动态)语言的一个关键性质.这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等等).superclass(例如O

  • java 利用反射机制,获取实体所有属性和方法,并对属性赋值

    一个普通的实体Person: private int id; private String name; private Date createdTime; ... //其它字段 // get set方法 ............... 现在需要把通过webService传过来的实体Person里面的所有字段的null值,换成"" 实现思路: 1.获取实体的所有字段,遍历 2.获取字段类型 3.调用字段的get方法,判断字段值是否为空 4.如果字段值为空,调用字段的set方法,为字段赋值

  • Java学习之反射机制及应用场景介绍

    前言: 最近公司正在进行业务组件化进程,其中的路由实现用到了Java的反射机制,既然用到了就想着好好学习总结一下,其实无论是之前的EventBus 2.x版本还是Retrofit.早期的View注解框架都或多或少的用到Java的反射机制. 什么是Java反射机制? JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的以及动态调用对象的方法的功能称为Java的反射机制. 反射机制提供了哪些功能? 在运行时判定

  • Java中的反射机制详解

    Java中的反射机制详解 反射,当时经常听他们说,自己也看过一些资料,也可能在设计模式中使用过,但是感觉对它没有一个较深入的了解,这次重新学习了一下,感觉还行吧! 一,先看一下反射的概念: 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义. 反射是Java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接.但是反射使用不当会成本很高! 看概念很晕的,继续往下

  • Java反射机制深入理解

    Java反射机制深入理解 一.概念 反射就是把Java的各种成分映射成相应的Java类. Class类的构造方法是private,由JVM创建. 反射是java语言的一个特性,它允程序在运行时(注意不是编译的时候)来进行自我检查并且对内部的成员进行操作.例如它允许一个java的类获取他所有的成员变量和方法并且显示出来.Java 的这一能力在实际应用中也许用得不是很多,但是在其它的程序设计语言中根本就不存在这一特性.例如,Pascal.C 或者 C++ 中就没有办法在程序中获得函数定义相关的信息.

  • Java 反射机制详解及实例代码

    Java反射详解 本篇文章依旧采用小例子来说明,因为我始终觉的,案例驱动是最好的,要不然只看理论的话,看了也不懂,不过建议大家在看完文章之后,在回过头去看看理论,会有更好的理解. 下面开始正文. [案例1]通过一个对象获得完整的包名和类名 package Reflect; /** * 通过一个对象获得完整的包名和类名 * */ class Demo{ //other codes... } class hello{ public static void main(String[] args) {

  • 老生常谈Java反射机制(必看篇)

    什么是反射机制 反射是java语言的一个特性,它允程序在运行时(注意不是编译的时候)来进行自我检查并且对内部的成员进行操作.例如它允许一个java的类获取他所有的成员变量和方法并且显示出来.这个能特定我们不常看到,但是在其他的比如C或者C++语言中很不就存在这个特性.一个常见的例子是在JavaBean中,一些组件可以通过一个构造器来操作.这个构造器就是用的反射在动态加载的时候来获取的java中类的属性的. 主要的类 Class 类的实例表示正在运行的 Java 应用程序中的类和接口.Class没

  • 老生常谈Java字符串进阶(必看篇)

    前言 最常用的对字符串操作的类有三个,分别是String,StringBuilder,StringBuffer,下面将会详细的说说这三个类...... String String类代表字符串,这个是最基本的对字符串的类,这个也是使用比较多的类,这里就不再详细介绍了 构造 new String(String str) new String(StringBuilder str) new String(StringBuffer str) new String(byte[] bys,String cha

  • 老生常谈Java String字符串(必看篇)

    Java中字符串对象创建有两种形式,一种为字面量形式,如String str = "hello";,另一种就是使用new这种标准的构造对象的方法,如String str = new String("hello"); 对于这样的常识,不再赘述. 首先String类是final类,为什么定义成final形式呢? 简单点说,对于如此高频率被使用的数据类型,设计者们认为已经设计的足够优秀了,不需要被继承,否则胡乱继承重写可能会降低程序的性能. 正如标题所述,既然深入,那我们

  • 老生常谈Java动态编译(必看篇)

    一.动态编译简介 new创建对象是静态加载类,在编译时刻就需要加载所有可能使用到的类. 一百个类,有一个类错了,都无法编译. 通过动态加载类可以解决该问题 二.代码实例 2.1 OfficeBetter.java main接口 里面通过对Class类的动态编译 然后调用实例,完成动态编译 public class OfficeBetter { public static void main(String[] args) throws InstantiationException, Illegal

  • 老生常谈Java虚拟机垃圾回收机制(必看篇)

    在Java虚拟机中,对象和数组的内存都是在堆中分配的,垃圾收集器主要回收的内存就是再堆内存中.如果在Java程序运行过程中,动态创建的对象或者数组没有及时得到回收,持续积累,最终堆内存就会被占满,导致OOM. JVM提供了一种垃圾回收机制,简称GC机制.通过GC机制,能够在运行过程中将堆中的垃圾对象不断回收,从而保证程序的正常运行. 垃圾对象的判定 我们都知道,所谓"垃圾"对象,就是指我们在程序的运行过程中不再有用的对象,即不再存活的对象.那么怎么来判断堆中的对象是"垃圾&q

  • 命令提示符编译java的方法(必看篇)

    先新建一个文件夹kun,kun就是类所在的package.新建一个java文件. HelloWorld.java的代码如下: package kun; public class HelloWorld{ public static void main(String[] args) { System.out.println("hello world"); A a=new A(); a.setValue(120); System.out.println(a.getValue()); } }

  • 老生常谈onTouch和onTouchEvent(必看篇)

    1.onTouch和onTouchEvent,都是在dispatchTouchEvent()中调用,onTouch优先于onTouchEvent执行.如果在onTouch方法中通过返回true将事件消费掉,onTouchEvent将不会再执行.另外需要注意的是,onTouch能够得到执行需要两个前提条件,第一mOnTouchListener的值不能为空,第二当前点击的控件必须是enable的.因此如果你有一个控件是非enable的,那么给它注册onTouch事件将永远得不到执行.对于这一类控件,

  • 老生常谈Java网络编程TCP通信(必看篇)

    Socket简介: Socket称为"套接字",描述IP地址和端口.在Internet上的主机一般运行多个服务软件,同时提供几种服务,每种服务都打开一个Socket,并绑定在一个端口上,不同的端口对应于不同的服务.Socket和ServerSocket类位于java.net包中.ServerSocket用于服务端,Socket是建立网络连接时使用的.连接成功时,应用程序两端都会产生一个Socket实例,通过操作这个实例完成所需会话. Socket常用方法: -int getLocalP

  • 老生常谈反射之Class类的使用(必看篇)

    任何一个类都是Class类的实例对象,这个实例对象有三种表示方式 第一种表示方式(任何一个类都有一个隐含的静态成员变量class): Class c1 = Foo.class; 第二种表示方式(已知该类对象,通过getClass方法): Foo foo1 = new Foo(); 2 Class c2 = foo1.getClass(); ※ c1.c2表示了Foo类的类类型(class type) 第三种表示方式 Class c3 = null; try { c3 = Class.forNam

  • 一个牛人给Java初学者的建议(必看篇)

    给初学者之一:浅谈Java及应用学java 从不知java为何物到现在一个小小的j2ee项目经理虽说不上此道高手,大概也算有点斤两了吧每次上网,泡bbs逛论坛,没少去java相关的版 面总体感觉初学者多,高手少,精通的更少由于我国高等教育制度教材陈旧,加上java自身发展不过十年左右的时间还有一个很重要的原因就是java这门语 言更适合商业应用所以高校里大部分博士老师们对此语言的了解甚至不比本科生多在这种环境下,很多人对java感到茫然,不知所措,不懂java能做什么即 便知道了java很有用,

随机推荐