JAVA反射详解

JAVA反射

目标

了解:

  1. 、使用反射访问方法和属性
  2. 、使用反射动态创建和访问数组

理解

  1. 、反射的概念和应用场合
  2. 、使用反射获取类的信息
  3. 、使用反射创建对象

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

 

Java反射有三个动态性质:

  1. 、运行时生成对象实例
  2. 、运行期间调用方法
  3. 、运行时更改属性

通过这些动态性质,JAVA反射可以在程序运行时获取对象和类的真实信息。

Java反射可以实现的功能:

  1. 在运行时判断任意一个对象所属的类
  2. 在运行时构造任意一个类的对象
  3. 在运行时判断任意一个类所具有的方法和属性
  4. 在运行时调用任意一个对象的方法
  5. 、生成动态代理

什么情况下运用JAVA反射呢?如果编译时根本无法预知对象和类可能属于哪些类,程序只依靠运行时信息来发现该对象和类的真实信息,此时就必须使用反射

 

JAVA反射API:反射API用来生成当前JAVA虚拟机中的类、接口或对象的信息

Class类

反射的核心类,可以获取类的属性、方法等内容信息

Field类

Field和Method和Constructor类都定义于Java.lang.reflect包下

Field表示类的属性,可以获取和设置类中属性的值

Method类

表示类的方法,它可以用来获取类中方法的信息,或者执行方法

Constructor类

表示类的构造方法

 

演示一:演示通过java反射API得到类的信息:

---------------------  Product类  ---------------------

package com.hp.entity;

 

public class Product {

private int proId;

private String proName;

private int getProId() {

return proId;

}

private void setProId(int proId) {

this.proId = proId;

}

public String getProName() {

return proName;

}

public void setProName(String proName) {

this.proName = proName;

}

public String toString(){

return "产品编号:"+this.proId+",名称:"+this.proName;

}

}

 

---------------------  反射测试类类  ---------------------

package com.hp.test;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

/*

 *  通过类的全路径,来获得该类的成员方法和成员属性

 */

public class Test {

public static void main(String[] args) {

try {

//根据类的全路径进行类加载,返回该类的Class对象

Class ca = Class.forName("com.hp.entity.Product");

//利用Class对象ca的自审,返回方法对象集合

Method[] methods = ca.getDeclaredMethods();

//遍历method数组,并输入方法信息

System.out.println("*****  获取方法信息  *****");

for(Method method : methods){

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

}

System.out.println("*****  获取方法信息结束  *****");

 

//利用Class对象ca的自审,返回成员属性对象信息

Field[] fileds = ca.getDeclaredFields();

System.out.println("*****  获取属性信息  *****");

for(Field filed : fileds){

System.out.println(filed.toString());

}

System.out.println("*****  获取属性信息结束  *****");

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}

}

 

结果如下:

*****  获取方法信息  *****

public java.lang.String com.hp.entity.Product.toString()

private int com.hp.entity.Product.getProId()

private void com.hp.entity.Product.setProId(int)

public java.lang.String com.hp.entity.Product.getProName()

public void com.hp.entity.Product.setProName(java.lang.String)

*****  获取方法信息结束  *****

*****  获取属性信息  *****

private int com.hp.entity.Product.proId

private java.lang.String com.hp.entity.Product.proName

*****  获取属性信息结束  *****

 

  1. 是使用JAVA反射机制,需要遵循三个步骤:
  1. 获得想操作的类的java.lang.Class对象
  2. 调用Class类的诸如getXXXMethods()方法用来得到对象的方法和属性等信息
  3. 使用反射API来操作这些信息。

注意:这上面这些步骤之前,首先当然要导入java.lang.reflect包下要用到的类

演示二:获取Class对象的三种方式

  1. 方式一:使用Class.forName()获取class对象

例:Class ca = Class.forName("com.hp.entity.Product");

  1. 方式二:使用对象的getClass()获取

例:Product product=new Product();

Class ca = product.getClass();

  1. 方式三:通过类的class属性获取(如果你在开发中需要使用反射,推荐这种方式)

例:Class ca=Product.class;

演示三:使用JAVA反射提供的丰富的API来获取一个类的详细信息

---------------------  Product类  ---------------------

package com.hp.entity;

@Deprecated

public class Product {

public Product(){

 

}

public Product(int proId){

this.proId=proId;

}

private Product(int proId,String proName){

this.proId=proId;

this.proName=proName;

}

 

private int proId;

private String proName;

private int getProId() {

return proId;

}

private void setProId(int proId) {

this.proId = proId;

}

public String getProName() {

return proName;

}

public void setProName(String proName) {

this.proName = proName;

}

public String toString(){

return "产品编号:"+this.proId+",名称:"+this.proName;

}

public void showInfo(){

System.out.println("产品编号:");

}

class Price{

}

}

---------------------  反射示例类  ---------------------

package com.hp.test;

 

import java.lang.annotation.Annotation;

import java.lang.reflect.Constructor;

import java.lang.reflect.Method;

 

import com.hp.entity.Product;

 

public class Test2 {

public static void main(String[] args) {

/*获取Product类的Class对象*/

Class ca = Product.class;

System.out.println("*******   获得指定构造  *******");

 

try {

Constructor con= ca.getConstructor(int.class);

System.out.println(con.toString());

} catch (SecurityException e1) {

e1.printStackTrace();

} catch (NoSuchMethodException e1) {

e1.printStackTrace();

}

 

    /*获取Product类的全部的构造方法*/

Constructor[] cstr = ca.getDeclaredConstructors();

System.out.println("******* Product的全部构造方法********");

for(Constructor c : cstr){

System.out.println(c.toString());

}

/*获取Product类的public构造方法*/

Constructor[] cstr_pub = ca.getConstructors();

 

System.out.println("******* Product的全部public构造方法********");

for(Constructor c : cstr_pub){

System.out.println(c.toString());

}

/*获取Product类的public方法*/

Method[] methods=ca.getMethods();

System.out.println("******* Product的全部public方法********");

for(Method m : methods){

System.out.println(m.toString());

}

/*获取Product类的名为指定方法*/

try {

System.out.println("****** Product不带参数的名为showInfo方法 *****");

Method method = ca.getMethod("showInfo", null);

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

} catch (SecurityException e) {

e.printStackTrace();

} catch (NoSuchMethodException e) {

e.printStackTrace();

}

/*获取Product类的全部注解*/

Annotation[] anno=ca.getAnnotations();

System.out.println("******  Product的全部注解  *****");

for(Annotation an : anno){

System.out.println(an.toString());

}

/*获取Product类的包信息*/

Package pack=ca.getPackage();

System.out.println("****  Product类的包信息  *****");

System.out.println(pack.toString());

/*获取Product类的内部类*/

Class[] prices = ca.getDeclaredClasses();//返回内部类

System.out.println("*******  Product的内部类  ******");

for(Class c : prices){

System.out.println(c.toString());

}

/*也可以通过内部类获取它的Class对象*/

try {

Class cla=Class.forName("com.hp.entity.Product$Price");

System.out.println("*******   Product的内部类具体信息 *****");

System.out.println("cla对应类的外部类是:"+cla.getDeclaringClass());

System.out.println("cla对应类的包:"+cla.getPackage());

System.out.println("cla对应类的父类:"+cla.getSuperclass());

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}

}

演示四:使用JAVA反射来创建类的实例

package com.hp.test;

 

import java.lang.reflect.Constructor;

import java.lang.reflect.InvocationTargetException;

 

import com.hp.entity.Product;

 

public class Test3 {

 

public static void main(String[] args) {

/*

 * 通过反射来生成对象有两种方式:

 * 1.使用newInstance()创建对象:利用默认构造方法创建实例

 * 2.使用Constructor对象创建对象:使用指定构造方法创建实例

 * */

Class ca=Product.class;

try {

********************使用newInstance创建对象*****************

Product p = (Product)ca.newInstance();

p.setProName("华为mate9");

System.out.println(p.getProName());

/*

 * 通常我们不使用反射创建对象,毕竟通过反射创建对象时性能稍微低一些,

 * 实际上,只有当程序需要动态创建某个类的对象时才会考虑使用反射,通常在开发通用性比较广的框架,

 * 基础平台时可能会大量使用反射;因为在许多JAVAEE框架中,都需要根据配置文件信息来创建JAVA对象,

 * 从配置文件读取的只是某个类的字符串类名,程序想通过字符串来创建对象的实例,就必须使用反射,比如spring框架就应用了反射技术

 * */

} catch (InstantiationException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

}

********************使用构造方法的newInstance创建对象*****************

 

try {

Constructor cu = ca.getConstructor(int.class);

Product p2=(Product)cu.newInstance(1008);

System.out.println(p2.getProId());

} catch (Exception e) {

e.printStackTrace();

}

}

}

 

演示五:使用JAVA反射来调用方法

package com.hp.test;

 

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

 

import com.hp.entity.Product;

 

public class Test4 {

public static void main(String[] args) {

/***  使用反射调用方法     ***/

Class ca=Product.class;

try {

Product p = (Product)ca.newInstance();

Method m = ca.getMethod("setProName", String.class);

//invlke可以调用Method对象对应的方法

m.invoke(p, "华为nova手机");

System.out.println(p.getProName());

/*

 * 注意:如果setProId为私有的

 * */

//注意:这里要使用getDeclaredMethod才能访问到私有的方法

Method m2=ca.getDeclaredMethod("setProId", int.class);

m2.setAccessible(true);//setAccessible为true则表示取消JAVA语言访问权限检查

m2.invoke(p, 108);

System.out.println(p.getProId());

 

} catch (Exception e) {

e.printStackTrace();

}

}

}

演示六:使用JAVA反射获取类的属性

package com.hp.test;

import java.lang.reflect.Field;

import com.hp.entity.Product;

public class Test5 {

public static void main(String[] args) {

Product p = new Product();

Class ca = p.getClass();

try {

//获取Product类的各种访问级别的proName属性

Field field= ca.getDeclaredField("proName");

//设置通过反射访问Field时取消权限检查,就可以访问私有属性

field.setAccessible(true);

field.set(p, "三星note5");

System.out.println(p.getProName());

}  catch (Exception e) {

e.printStackTrace();

}

}

}

 

演示七:使用JAVA反射动态创建数组及访问数组

package com.hp.test;

 

import java.lang.reflect.Array;

 

public class Test6 {

public static void main(String[] args) {

//创建一个元素类型为String,长度为3的数组

Object arr = Array.newInstance(String.class, 3);

//依次为arr数组中index为0,1,2的元素赋值

Array.set(arr, 0, "荣耀盒子");

Array.set(arr, 1, "荣耀8手机");

Array.set(arr, 2, "华为mate9保时捷版");

        //取出arr数组中index为0,1,2的元素的值

Object o1= Array.get(arr, 0);

Object o2= Array.get(arr, 1);

Object o3= Array.get(arr, 2);

 

System.out.println(o1);

System.out.println(o2);

System.out.println(o3);

}

}

 

 

你可能感兴趣的:(JAVA反射详解)