博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java反射
阅读量:7247 次
发布时间:2019-06-29

本文共 10433 字,大约阅读时间需要 34 分钟。

什么是Java反射机制?有什么用?

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

  • Java的反射机制它知道类的基本结构,这种对Java类结构探知的能力,我们称为Java类的“自审”。

Java反射机制主要提供了以下功能

在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。 用实例 来说明

class 类的使用:获取类的属性、方法、构造方法、类的相关信息

import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;/**  * * @author lijian  *class 类的使用:获取类的属性、方法、构造方法、类的相关信息  */public class TestClass_1 {      public static void main(String[] args) throws ClassNotFoundException {  	       //forName(String className)返回与带有给定字符串名的类或接口相关联的 Class 对象。          Class clazz = Class.forName("java.lang.String");         //getDeclaredFields();返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段,包括公共、保护、默认(包)访问和私有字段,但不包括继承的字段。          Field[] field = clazz.getDeclaredFields();          System.out.println("---------------------显示类的属性----------------------------");          for (Field f : field) {              //getName()返回此 Field 对象表示的字段的名称              //getType()返回一个 Class 对象,它标识了此 Field 对象所表示字段的声明类型。              System.out.println(f.getName() + "        " + f.getType());          }  		        System.out.println("---------------------显示类的方法-----------------------------");          //getDeclaredMethods() 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。          Method[] method = clazz.getDeclaredMethods();          for (Method m : method) {              System.out.println(m.getName());          }          System.out.println("---------------------显示类的构造方法-----------------------------");          //getDeclaredConstructors() 返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。         Constructor[] constructors = clazz.getDeclaredConstructors();         for(Constructor c:constructors)         {             System.out.println(c);         }        System.out.println("----------------------获取类的相关的信息----------------------------------------------");        System.out.println("类所在的包为:"+ clazz.getPackage().getName());        System.out.println("类名:"+ clazz.getName());        System.out.println("父类的名称:"+ clazz.getSuperclass().getName());              }  }复制代码

以下示例中会使用到User.java类,其代码如下:

public class User {        private String name;      private int age;           public User(){}      public User(String name, int age) {      }  属性的setter 和getter 方法 省略······  复制代码

生成一个类的Class对象有一下四种方式

import entity.User;    /**  *   * @author lijian   * 创建Class对象的4种方法  */  public class TestClass_2 {        public static void main(String[] args) throws ClassNotFoundException {          User user = new User();          // 第一种:对象.Class          Class clazz = user.getClass();          // 使用包装器获取Class 对象          String str = "asdasd";          clazz = str.getClass();          // 第二种 :类.class          clazz = User.class;          clazz = String.class;          clazz = Integer.class;            // 第三种:Class.forname();          clazz = Class.forName("java.lang.String");          clazz = Class.forName("java.lang.Long");                   //第四种:包装类.type          clazz = Integer.TYPE;      }  }  复制代码

使用反射动态创建对象实例有两种方式:

  • 通过Class的newInstance()方法 该方法要求该Class 对象的对应类有无参构造方法,执行newInstance()实际上就是执行无参构造方法来创建该类的实例
  • 通过Constructor的newInstance() 方法 先使用Class对象获得指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建该Class对象对应类的对象 通过该方法可以选择使用指定的构造方法来创建对象 两种方法写个简单的实例
import java.lang.reflect.Constructor;  import entity.User;    /**  *   * @author lijian  *  使用反射 动态创建对象  两种方式  */  public class TestClass_3 {      public static void main(String[] args) throws Exception {          /**          * 方法1:通过Class的newInstance()方法          *          该方法要求该Class对象的对应类有无参构造方法          *              执行newInstance()实际上就是执行无参构造方法来创建该类的实例          */      //      Class  clazz = Class.forName("entity.User");      //  Object obj =  clazz.newInstance();                    /**          * 方法2:通过Constructor的newInstance()方法          *             先使用Class对象获取指定的Constructor对象          *             再调用Constructor对象的newInstance()方法来创建该Class对象对应类的对象          *              通过该方法可选择使用指定构造方法来创建对象          */          Class clazz = Class.forName("entity.User");          //指定有参的构造方法          Constructor cons = clazz.getConstructor(new Class[] {int.class,String.class,String.class});          //使用有参数的构造方法实例对象                  Object obj = cons.newInstance(new Object[]{1,"scott","1234"});                  //转换为实际操作类                  User user = (User)obj;                    //也可以调用无参构造方法,比第一种方法复杂                  obj = clazz.getConstructor(new Class[]{}).newInstance(new Object[]{});                  user = (User)obj;                  //以下也可以调用无参构造方法                  obj = clazz.getConstructor().newInstance();                  //转换为实际操作类                   user = (User)obj;      }    }  复制代码

使用反射动态修改查询的属性值

通过Class对象的getFields() 或者getField()方法可以获得该类所包括的全部Field属性或指定Filed属性。Field类提供了以下方法来方法访问属性

getXxx(Object obj) :获取obj对象该Field的属性值。此处的Xxx对应8个基本数据类型,如果该属性类型是引用类型则直接使用get(Objectobj) setXxx(Object obj,Xxx val) :将obj对象的该Field赋值val。此处的Xxx对应8个基本数据类型,如果该属性类型是引用类型则直接使用set(Objectobj, Object val) setAccessible(Boolean flag):若flag为true,则取消属性的访问权限控制,即使private属性也可以进行访问

import java.lang.reflect.Field;    /**  *   * @author lijian  *    使用反射动态修改查询属性值  */  public class TestClass_4 {        public static void main(String[] args) throws Exception {          Class clazz = Class.forName("entity.User");          Object obj = clazz.newInstance();//获得类的实例          //获得 User 类中的指定属性对应的Field对象(每个属性对应一个Field对象)          Field field = clazz.getDeclaredField("name");                    //取消属性的访问权限控制,即使private 属性也可以进行访问          field.setAccessible(true);          //调用 getter 方法获取属性值          System.out.println(field.get(obj));          //调用setter 方法给属性赋值          field.set(obj, "scott");          //调用 getter 方法获取对应属性修改后的值          System.out.println(field.get(obj));      }  }  复制代码

使用反射动态执行方法

  • 通过Class对象的getMethods()方法可以获得该类所包括的全部方法,返回值是Method[]
  • 通过Class对象的getMethod() 方法可以获得该类所包括的执行方法,返回值是Method,每个Method对象对应一个方法,获得Method对象后,可以调用其invoke()来调用对应方法 Objectinvoke(Object obj , Object [] args): obj代表当前方法所属的对象的名字, args代表当前方法的参数列表,返回值Object是当前方法的返回值,即执行当前方法的结果。
import java.lang.reflect.Method;  import entity.User;    /**  *   * @author lijian  *  使用反射动态执行方法  */  public class TestClass_5 {        public static void main(String[] args) throws Exception{                    Class clazz = User.class;          Object obj = clazz.newInstance();                              //调用该对象的 setName方法          Method method = clazz.getMethod("setName", new Class[]{String.class});          Object result =method.invoke(obj, new Object[]{
"scott"}); // obj.setName("scott"); System.out.println("返回值为:"+result); //调用对象的getName()方法 Method method1 = clazz.getMethod("getName", new Class[]{}); Object obj1 = method1.invoke(obj, new Object[]{}); System.out.println("返回值为:"+obj1); } } 复制代码

使用反射动态创建数组并存取元素

在java.lang.reflect包下提供了Array类,包括一系列static方法,通过这些方法可动态的创建数组、给元素赋值、取出元素值等

Array提供的主要方法如下:

  • static ObjectnewInstance(Class<?> componentType, int[] dim) :创建一个具有指定的组件类型和维度的新数组
  • static void setXxx(Objectarray, int index ,xxx val):给数组对象array中第index个元素赋值val
  • static xxx getXxx(Objectarray, int index):以 xxx形式返回指定数组对象array中第index个元素值

1️⃣ 动态创建一维数组,并给数组赋值:

import java.lang.reflect.Array;    /**  *   * @author lijian  *  动态创建一维数组,并给数组赋值:  */  public class TestClass_6 {        public static void main(String[] args) throws Exception  {               Class clazz = Class.forName("java.lang.Integer");            Object array = Array.newInstance(clazz, 10);//根据类的class 创建大小为10的数组            Array.set(array, 5, 10);//给数组的第5个元素赋值为10            Object el = Array.get(array, 5);//取出数组的第5个元素值显示            System.out.println(el);      }    }  复制代码

2️⃣ 动态创建二维数组,并给数组赋值:

import java.lang.reflect.Array;    /**  *   * @author lijian  *动态创建二维数组,并给数组赋值:  */  public class TestClass_7 {        public static void main(String[] args) {          int dims[] = {10,15};          Object  array = Array.newInstance(int.class, dims);//创建一个10行15列二维数组,等价与:array[10][15]          Object  array1 = Array.get(array, 5);//获取二维数组中的第5行          Array.set(array1, 8, 300);     //给数组的第5行8列赋值300,等价与:array[5][8]=300          Object el = Array.get(array1, 8);//取出数组中第5行8列的值          System.out.println(el);      }  }  复制代码
  • Standard annotation type(Built-in annotation):@Override(when extends parent),@SuppressWarnings(wipe off the warnings)
  • Meta annotation type(decorate other annotation definition):@Target,@Retention
  • user-defined(define by oneself,it is an interface):use the key @interface to define

for example:

//define the annotation DBFieldpackage annotationimport java.lang.Retention;import java.lang.Target;import java.lang.RetentionPolicy;import java.lang.ElementType;@Target(Element.Field)@Retention(RetentionPolicy.Runtime)public @interface DBField {public String getDBField() default "SQL";     }//DAO use the annotationpackage annotation;public class UserInfoDAO {@DBFiledObject obj;     }//the result is SQLimport annotation.DBField;public class TestAnnotation{     public static void main(String args[]){     Class
alz = Class.forName("annotation.UserInfoDAO"); Field fields[] = clz.getDeclaredFields(); for(Field f : fields){ Systom.out.println(f.getName()); Annotation[] annField=f.getAnnotations(); if(annField[0] instanceof DBField){ System.out.println(((DBField)annField[0]).getDBField()) } } }}复制代码

JAVA-反射-getGenericSuperclass()介绍

public class Person
{ } import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; public class Student extends Person
{ public static void main(String[] args) { Student st=new Student(); Class clazz=st.getClass(); //getSuperclass()获得该类的父类 System.out.println(clazz.getSuperclass()); //getGenericSuperclass()获得带有泛型的父类 //Type是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。 Type type=clazz.getGenericSuperclass(); System.out.println(type); //ParameterizedType参数化类型,即泛型 ParameterizedType p=(ParameterizedType)type; //getActualTypeArguments获取参数化类型的数组,泛型可能有多个 Class c=(Class) p.getActualTypeArguments()[0]; System.out.println(c); } }打印结果: class com.test.Person29 com.test.Person
class com.test.Student复制代码

转载于:https://juejin.im/post/5b44233e5188251b1b44776a

你可能感兴趣的文章
01hibernate_first
查看>>
对LigerUI控件库进行扩展,自定义extend和override,并扩展事件前与事件后
查看>>
Tengine——安装起来真费劲
查看>>
关于Oracle过程,函数的经典例子及解析
查看>>
Android-PullToRefresh(一)
查看>>
JavaScript+XML+VBA导出报表初步构想
查看>>
UVA1452|LA4727-----Jump------经典的约瑟夫公式的变形(DP)
查看>>
Android SDK安装教程
查看>>
sourceinsight 相对路径设置
查看>>
mysql describe
查看>>
程序员的自我修养 学习笔记(5)
查看>>
DNS安全浅议、域名A记录(ANAME),MX记录,CNAME记录 专题
查看>>
数据字典生成工具之旅(9):多线程使用及介绍
查看>>
Java编程思想学习笔记——注解
查看>>
使用HTML5新特性Mutation Observer实现编辑器的撤销和撤销回退操作
查看>>
Java可变参数传递中可以接收多个对象
查看>>
Python中的正则表达式(re)
查看>>
2016 新学++ , 回顾过去展望未来
查看>>
让你在DOS中任意切换目录
查看>>
较完整的轮播图特效
查看>>