zoukankan      html  css  js  c++  java
  • Java反射,获取类的公有、私有的构造函数(有参,无参)、方法(有参,无参)、属性

        Class类与java.lang.reflect类库一起对反射进行了支持,该类库包含Field、Method和Constructor类,这些类的对象由JVM在启动时创建,用以表示未知类里对应的成员。这样的话就可以使用Contructor创建新的对象,用get()和set()方法获取和修改类中与Field对象关联的字段,用invoke()方法调用与Method对象关联的方法。另外,还可以调用getFields()、getMethods()和getConstructors()等许多便利的方法,以返回表示字段、方法、以及构造器对象的数组,这样,对象信息可以在运行时被完全确定下来,而在编译时不需要知道关于类的任何事情。

        首先创建一个类

     1 public class Per {
     2      public String name="sunshine";
     3      private int age=28;
     4      public double weight=65.50;
     5      
     6      public Per(){
     7          System.out.println("测试反射获取公有无参构造函数");
     8      }
     9      private Per(String name){
    10          this.name=name;
    11          System.out.println("测试反射获取私有有参构造函数");
    12      }
    13      public Per(String name,int age){
    14          this.name=name;
    15          this.age=age;
    16          System.out.println("测试反射获取公有有多个参数构造函数name:"+name+"    age:"+age);17      }
    18      public String methodT1(){
    19          System.out.println("测试反射获取公有无参方法");
    20          return null;
    21      }
    22      public String methodT1(String name,int age){
    23          System.out.println("测试反射获取公有多个参方法");
    24          System.out.println(name+":"+age);
    25          return null;
    26      }
    27      private String methodT1(String name){
    28          System.out.println("测试反射获取私有有参方法");
    29          System.out.println("name:"+name);
    30          return null;
    31      }
    32      public String methodT2(int[] arr,String[] str){
    33          System.out.println("测试反射获取公有有数组参方法");
    34          System.out.println("int[] arr:"+arr+"String[] str:"+str);
    35          return null;
    36      }
    37      public static void main(String[] args) {
    38         System.out.println("测试反射获取main方法");
    39     }
    40 }

        1.使用java反射获取类的构造函数(公有、私有)(有参,无参)

     1 import java.lang.reflect.Constructor;
     2 import java.lang.reflect.Field;
     3 import java.lang.reflect.Method;
     4 
     5 import org.junit.AfterClass;
     6 import org.junit.BeforeClass;
     7 import org.junit.Test;
     8 /**
     9  * 测试使用java反射获取类的构造函数并创建对象
    10  * @author Sunshine
    11  *
    12  */
    13 public class ReflectPer {
    14     private static Class class1;
    15     //因为java反射获取类时都需要加载类,在这里我就使用Junit的@beforeclass来去加载类,不用在每个测试方法中重复创建
    16     //注:@beforeclass在执行测试方法前运行
    17     @BeforeClass
    18     public static void beforeClass() throws Exception{
    19         System.out.println("====测试方法启动前先加载类====");
    20         class1 = Class.forName("myPractise.Per");//加载类
    21     }
    22     //获取类的公有无参构造函数,并创建对象
    23     @Test
    24     public void test1() throws Exception{
    25         Constructor constructor = class1.getConstructor(null);//获取公有无参构造器,值为null代表获取无参构造器
    26         Per per = (Per) constructor.newInstance(null);//创建对象,返回的是Object类型要强转
    27         System.out.println(per.name);//可以调用类的属性-----成功
    28     }
    29     //获取类的公有参构造函数,并创建对象
    30     @Test
    31     public void test2()throws Exception{
    32         Constructor constructor = class1.getConstructor(String.class,int.class);//获取公有多个参数构造器,参数为构造器中参数的类型
    33         Per per = (Per)constructor.newInstance("baby",24);//创建对象
    34     }
    35     //获取类的私有有参构造函数,并创建对象
    36     @Test
    37     public void test3()throws Exception{
    38         Constructor constructor = class1.getDeclaredConstructor(String.class);//获取公有多个参数构造器,参数为构造器中参数的类型
    39         constructor.setAccessible(true);//暴力反射,只有将属性设置为true才可以创建对象
    40         Per per = (Per)constructor.newInstance("baby");
    41         System.out.println(per.weight);//可以调用类的属性-----成功
    42         //注:通常情况下一个类不可以访问另一个类的私有的属性,方法。。但是通过java反射可以
    43     }
    44     @AfterClass
    45     public static void afterClass(){
    46         System.out.println("===测试完成将对象赋值为null===");
    47     }
    48 }

       2.使用java反射获取类的方法(公有、私有)(有参,无参)

     1 import java.lang.reflect.Constructor;
     2 import java.lang.reflect.Field;
     3 import java.lang.reflect.Method;
     4 
     5 import org.junit.AfterClass;
     6 import org.junit.BeforeClass;
     7 import org.junit.Test;
     8 /**
     9  * 测试使用java反射获取类方法
    10  * @author Sunshine
    11  *
    12  */
    13 public class ReflectPer {
    14     private static Class class1;
    15     private static Per per;
    16     //因为java反射获取类时都需要加载类,在这里我就使用Junit的@beforeclass来去加载类,不用在每个方法中重复创建
    17     //注:@beforeclass在执行测试方法前运行
    18     @BeforeClass
    19     public static void beforeClass() throws Exception{
    20         System.out.println("====测试方法启动前先加载类====");
    21         class1 = Class.forName("myPractise.Per");//加载类
    22         per = (Per) class1.getConstructor(null).newInstance(null);//使用反射创建对象
    23     }
    24     
    25     //获取类的公有无参方法
    26     @Test
    27     public void test4()throws Exception{
    28         Method method = class1.getMethod("methodT1", null);//获取指定的方法,参数为方法名和该方法的参数类型,因为我们这是测试无参的方法,所以传入null
    29         method.invoke(per, null);//使用invoke方法来调用,参数为指定对象,该方法传入的参数,因为我们这是测试无参的方法,所以传入null
    30     }
    31     //获取类的公有有参方法
    32     @Test
    33     public void test5()throws Exception{
    34         Method method = class1.getMethod("methodT1", String.class,int.class);//获取指定的方法,参数为方法名和该方法的参数类型
    35         method.invoke(per, "sunshine",25);//使用invoke方法来调用,参数为指定对象,该方法传入的参数
    36     }
    37     @Test
    38     public void test6()throws Exception{
    39         Method method = class1.getDeclaredMethod("methodT1", String.class);//获取指定的方法,参数为方法名和该方法的参数类型
    40         method.setAccessible(true);//暴力反射,默认为false,未设置则调用类的私有方法不成功
    41         method.invoke(per, "sunshine");//使用invoke方法来调用,参数为指定对象,该方法传入的参数
    42         System.out.println(method.getReturnType());//获取到该类指定方法的返回值类型
    43     }
    44     @Test
    45     public void test7()throws Exception{
    46         Method method = class1.getMethod("methodT2", int[].class,String[].class);
    47         method.invoke(per, new int[]{1,2},new String[]{"AA","BB"});
    48     }
    49     //获取某个类的main方法比较特殊也可以说是只要传入的参数为单个数组特殊
    50     //jdk5之后新增特性--可变参数
    51     //在加载时会将传入的数组进行拆分,这样就会报错,java.lang.IllegalArgumentException: wrong number of arguments 错误的参数个数
    52     //这时候我们可以欺骗一下虚拟机,告诉他我们传入的是一个对象将new String[]{"AA","BB"}换成(Object)new String[]{"AA","BB"}
    53     @Test
    54     public void test8()throws Exception{
    55         Method method = class1.getMethod("main",String[].class);
    56         method.invoke(per,(Object)new String[]{"AA","BB"});
    57     }
    58     @AfterClass
    59     public static void afterClass(){
    60         System.out.println("===测试完成将对象赋值为null===");
    61     }
    62 }

    3.使用java反射获取类的属性(公有、私有)

     1 import java.lang.reflect.Constructor;
     2 import java.lang.reflect.Field;
     3 import java.lang.reflect.Method;
     4 import java.util.Iterator;
     5 
     6 import org.junit.AfterClass;
     7 import org.junit.BeforeClass;
     8 import org.junit.Test;
     9 
    10 /**
    11  * 测试使用java反射获取类的属性
    12  * 
    13  * @author Sunshine
    14  *
    15  */
    16 public class ReflectPer {
    17     private static Class class1;
    18     private static Per per;
    19 
    20     // 因为java反射获取类时都需要加载类,在这里我就使用Junit的@beforeclass来去加载类,不用在每个测试方法中重复创建
    21     // 注:@beforeclass在执行测试方法前运行
    22     @BeforeClass
    23     public static void beforeClass() throws Exception {
    24         System.out.println("====测试方法启动前先加载类====");
    25         class1 = Class.forName("myPractise.Per");// 加载类
    26         per = (Per) class1.getConstructor(null).newInstance(null);// 使用反射创建对象
    27     }
    28     // 公有属性
    29     @Test
    30     public void test9() throws Exception {
    31         // 获取某个属性,参数是属性名
    32         Field field = class1.getField("name");
    33         // 输出属性值,需要传入指定对象
    34         System.out.println(field.get(per));
    35         // 获取属性的类型
    36         System.out.println(field.getType());
    37         // 获取多个属性
    38         Field[] field1 = class1.getFields();
    39         // 增强for循环Jdk1.5后的新特性,只适用于数组和实现了Iterator的集合
    40         for (Field str : field1) {
    41             System.out.println(str);
    42         }
    43         // 设置属性值
    44         field.set(per, "baby");
    45         System.out.println(field.get(per));
    46     }
    47     //私有属性
    48     @Test
    49     public void test10() throws Exception {
    50         Field field = class1.getDeclaredField("age");
    51         field.setAccessible(true);//暴力反射
    52         System.out.println(field.get(per));
    53     }
    54 
    55     @AfterClass
    56     public static void afterClass() {
    57         System.out.println("===测试完成将对象赋值为null===");
    58     }
    59 }
  • 相关阅读:
    三栏布局
    两栏布局
    WEB前端开发笔试题(1)
    JavaScript document 对象
    设计一个有3个超链接的页面,单击这些链接时分别打开和关闭窗口以及关闭本身窗口。
    在窗体中有两个多选列表,用户可以从左侧列表中选择任意项,添加到右侧列表中。反之亦然。
    How and when: ridge regression with glmnet
    Fitting Bayesian Linear Mixed Models for continuous and binary data using Stan: A quick tutorial
    An Introduction to Stock Market Data Analysis with R (Part 1)
    Lesser known purrr tricks
  • 原文地址:https://www.cnblogs.com/huangchunbao/p/10882092.html
Copyright © 2011-2022 走看看