java反射 javabean_java反射,JavaBean

packagecn.sxt.t01;import static org.junit.Assert.*;importjava.lang.reflect.Constructor;importjava.lang.reflect.Method;importjava.util.Date;importjava.util.Iterator;importorg.junit.Test;public classClassTest01 {private staticDate getObject;/*反射:(reflection):在运行时期,动态地去获取类中的信息(类的信息,方法信息,构造器信息,字段等信息进行操作);

一个类中包含的信息有: 构造器,字段,方法

如何使用反射描述这些相关的信息

Class : 描述类

Method : 描述方法

Constructor :描述构造器

Field :描述字段

**/@Testpublic void testName() throwsException {//编译类型//运行类型(真实类型)

Object obj = newjava.util.Date();//需求:根据对象obj调用Date类中的一个方法,toLocaleString,如何来做?//方案一: 强转

Date d =(Date)obj;

System.out.println(d.toLocaleString());

}//方案二: 使用反射

publicObject getObject() {return newjava.util.Date();

}

@Test//获取类的Class实例三种方式

public void testName1() throwsException {/** 在任何反射的操作之前,都必须先获取某一个类的字节码实例,任何一个类在jvm有且只有一份字节码实例

*

* 获取字节码实例有三种方式

* 1. 类名.class;

* 2. 对象.getClass();

* 3. Class.forName("类的全限定名");

* 全限定名 = 包名+类名

**/

//需求:获取User类的字节码实例//1. 类名.class;

Class clz1=Users.class;

System.out.println(clz1);//2. 对象.getClass();

Users users=newUsers();

Class> clz2=users.getClass();

System.out.println(clz2);//3. Class.forName("类的全限定名");//全限定名 = 包名+类名

Class> clz3 = Class.forName("cn.sxt.t01.Users");

System.out.println(clz3);

}

@Test//获取九大内置类的字节码实例

public void testName2() throwsException {/*对于对象来说,可以直接使用对象.getClass()或者Class.forName(className); 类名.class都可以获取Class实例.

但是我们的基本数据类型,就没有类的权限定名,也没有getClass方法.

问题: 那么如何使用Class类来表示基本数据类型的Class实例?

八大基本数据类型和 void关键字都是有 字节码实例的

byte,short,int,long,char,float,double,boolean ,void关键字

答 : 数据类型/void.class 即可

每个基本数据类型都是包装类型 如 :int ----Integer包装类型

注意: 基本数据类型和包装数据类型底层的字节码实例是不相同*/

//数据也是一种数据类型,也需要单独获取字节码实例 Class clz = 数据类型[].class//获取8大基本数据类型和void的字节码实例(以int,integer为列)//1.获取int类型的字节码实例

Class> intClz=int.class;

System.out.println(intClz);//其他七种基本数据类型 和 第一种相似....//获取void的字节码实例

Class > voidClz=void.class;

System.out.println(voidClz);//所有的基本数据类型都有包装类型//int---Integer//int 和Integer 的字节码是绝对不相等的

Class integeClz=Integer.class;

System.out.println(integeClz);

System.out.println(intClz== integeClz);//false//直接通过数组类型获取字节码实例

Class clz1=int[].class;

System.out.println(clz1);//定义一个数据

int[] arr1 = { 1, 2, 3, 5};

Class clz2=(Class)arr1.getClass();

System.out.println(clz2);//定义一个数据

int[] arr2 = { 10, 2, 3, 5};//3.获取arr1数组的字节码实例

Class clz3 = (Class) arr2.getClass();

System.out.println(clz3);

System.out.println(clz1== clz2);//true

System.out.println(clz3 == clz2);//true//所以不同数组的字节码实例是相同的

}

@Testpublic void testName3() throwsException {/*类的构函数有 有参数构造函数,无参构造函数,公共构造函数,非公共构造函数,根据不同的构造函数 Class提供了几种获取不同构造函数的方法

*

*

* 获取Users类的构造器

*

* 1.获取Users类的字节码实例

* 2.获取Users对应的构造器*/

//1.获取Users类的字节码实例

Class stu=Users.class;//2.获取所有的公共构造器

Constructor>[] constructors =stu.getConstructors();for(Constructor>constructor:constructors){

System.out.println(constructor);

}//3.获取所有的构造器(和访问权限无关)

Constructor>[] de =stu.getDeclaredConstructors();for(Constructor>constructor : de){

System.out.println(constructor);

}//4.获取指定的构造器(公共的)getConstructor

Constructor constructor1 = stu.getConstructor(String.class);

System.out.println(constructor1);//5. getDeclaredConstructor 获取和访问权限无关构造器

Constructor constructor2 = stu.getDeclaredConstructor(String.class,Integer.class);

System.out.println(constructor2);

}

@Testpublic void testName4() throwsException {/*调用构造器,创建对象

Constructor类:表示类中构造器的类型,Constructor的实例就是某一个类中的某一个构造器

常用方法:

public T newInstance(Object... initargs):如调用带参数的构造器,只能使用该方式.

参数:initargs:表示调用构造器的实际参数

返回:返回创建的实例,T表示Class所表示类的类型

如果:一个类中的构造器可以直接访问,同时没有参数.,那么可以直接使用Class类中的newInstance方法创建对象.

public Object newInstance():相当于new 类名();

调用私有的构造器:

*

**/

//需求: 使用反射创建Student的java对象//1.获取字节码实例//Class> clz = Class.forName("cn.sxt.t01.Users");

Class clz = (Class)Class.forName("cn.sxt.t01.Users");//2.获取指定构造器

Constructor cons1 = clz.getConstructor(String.class);//2.1获取私有构造函数

Constructor cons2 = clz.getDeclaredConstructor(String.class,Integer.class);//3.创建对象//3.1. 如果当前类的字节码有一个无参公共数构造器,可以直接使用字节码实例直接创建对象

Users n=clz.newInstance();

n.say();//3.2.使用构造器创建对象;

Users n1 = cons1.newInstance("dewjfe");//3.3使用私有构造函数创建//3.3.1设置忽略访问修饰的权限//如果是私有构造方法,反射默认是无法直接执行的,找到父类中AccessibleObject的方法,设置为true,即可忽略访问权限

cons2.setAccessible(true);

Users n3= cons2.newInstance("fewfew",20);

}

@Testpublic void testName5() throwsException {/*操作方法-Method

一个类创建对象以后,一般就要执行对象的方法等等,使用反射操作对象

首先要获取方法,再去执行,使用Class 获取对应的方法:

getMethods() 获取所有的公共方法,包括父类的公共方法

getDeclaredMethods() 获取所有本类的方法,包括本类的私有方法

getDeclaredMethod(String name, Class>... parameterTypes)

获取指定方法名称的方法,和访问权限无关

ame : 指定的方法名称

parameterTypes : 方法参数的类型

Method执行方法:方法获取以后就需要执行。Method对象中提供方法执行的功能

invoke(Object obj, Object... args)

执行方法

Obj :如果是对象方法,传指定的对象,如果是类方法,传 null

Args: 方法的参数

如果方法有返回结果,可以接收

获取方法和方法的执行

一个类中的方法有很多,无参,有参,静态,可变参数私有方法,等等,针对不同的方法处理,提供了不同的获取方案*/

/** 需求:获取Users类的方法*/

//1.获取Users的字节码实例

Class clz=Users.class;//2.通过类的字节码直接创建对象(必须保证类有一个无参数公共构造函数)

Users newInstance =clz.newInstance();//3.获取方法//3.1获取所有的公共方法(包含父类的方法)

Method[] methods =clz.getMethods();for(Method method : methods) {

System.out.println(method);

}//3.2获取当前类的所有的方法(不包含父类,和访问权限无关,成员或者静态方法都获取)

Method[] de =clz.getDeclaredMethods();for(Method method :de) {

System.out.println(method);

}//3.3获取指定名称的方法

Method hello1 = clz.getMethod("hello1");

System.out.println(hello1);//3.4 获取私有方法

Method hello3 = clz.getDeclaredMethod("hello3", String.class,int.class);

System.out.println(hello3);//3.5获取静态方法

Method staticMethod = clz.getDeclaredMethod("staticMethod", String.class);

System.out.println(staticMethod);//3.6获取有数组参数的方法

Method method1 = clz.getDeclaredMethod("method1", int[].class);

System.out.println(method1);

System.out.println("------------------------------------------------------------");

}

@Testpublic void testName6() throwsException {//1.获取Users的字节码实例

Class clz=Users.class;//2.通过类的字节码直接创建对象(必须保证类有一个无参数公共构造函数)

Users n =clz.newInstance();//3.获取方法//3.1获取指定名称的方法

Method hello1 = clz.getMethod("hello1");

System.out.println(hello1);//3.1.1执行无参数对象方法

hello1.invoke(n);//3.3 获取私有方法

Method hello3 = clz.getDeclaredMethod("hello3", String.class,int.class);

System.out.println(hello3);//3.3.1设置忽略访问权限

hello3.setAccessible(true);//3.3.2 执行私有方法

Object invoke = hello3.invoke(n, "令狐冲",30);

System.out.println( invoke);//3.4获取静态方法

Method staticMethod = clz.getDeclaredMethod("staticMethod", String.class);

System.out.println(staticMethod);//3.4.1执行静态方法

staticMethod.invoke(null, "金毛狮王");//3.5获取基本数据类型整数组参数的方法

Method method1 = clz.getDeclaredMethod("method1", int[].class);

System.out.println(method1);//3.5.1执行 数组参数的方法

int[] intArr = {1,2,5,10};

method1.invoke(null, newObject[] {intArr});//3.6获取基本数据类型整数组参数的方法

Method method2 = clz.getDeclaredMethod("method2", String[].class);

System.out.println(method2);//3.6.1执行字符串数组参数的方法

String[] stringArr = {"A","B","D"};//如果方法中有可变参数(数组),如果反射传递的可变参数是引用类型,底层有一个拆箱的功能,会将数组的元素拆成一个个参数传递过来//解决方案: 将数组外面在包装一层数组,如果拆箱一次,得到还是一个数组`

method2.invoke(null, newObject[] {stringArr});

}

@Testpublic void testName7() throwsException {/*操作字段(成员变量)-Field

* 类中的字段有各种数据类型和各种访问权限,针对这些情况,反射操作有对应的方法来获取和处理

* getFields() 获取当前Class所表示类中所有的public的字段,包括继承的字段.

* getDeclaredFields() 获取当前Class所表示类中所有的字段,不包括继承的字段.

* getField(String name) 获取当前Class所表示类中该fieldName名字的字段,不包括继承和私有的字段.

* getDeclaredField(String name):获取当前Class所表示类中该fieldName名字的字段,不包括继承的字段.

**/

/** Field类常用方法:

void setXX(Object obj, XX value) :为基本类型字段设置值,XX表示基本数据类型

void set(Object obj, Object value) :表示为引用类型字段设置值

参数:

obj: 表示字段底层所属对象,若该字段是static的,该值应该设为null

value: 表示将要设置的值

-------------------------------------------------------------------------------------

XX getXX(Object obj) :获取基本类型字段的值,XX表示基本数据类型

Object get(Object obj) :表示获取引用类型字段的值

参数:

obj: 表示字段底层所属对象,若该字段是static的,该值应该设为null

返回:返回该字段的值.

*

*

*

*set(Object obj, Object value)

设置引用类型的值,非基本数据类型

Obj: 要设置值得对象

Value : 要设置的值/

/*Field操作设置值/获取值

* 给某个类中的字段设置值和获取值:

1,找到被操作字段所在类的字节码

2,获取到该被操作的字段对象

3,设置值/获取值

**/

/** 需求:操作Users类的字段*/

//1.获取Users字节码实例

Class clz=Users.class;//1.1 通过字节码实例创建对象(必须保证有一个无参数public构造器)

Users n =clz.newInstance();//2.获取所有public字段

Field[] fields =clz.getFields();for(Field field : fields) {

System.out.println(field);

}//3.获取所有的字段(与访问权限无关)

Field[] declaredFields =clz.getDeclaredFields();for(Field field : declaredFields) {

System.out.println(field);

}//4.获取指定名称的public字段

Field field = clz.getField("name");//4.1为字段设置值

/** nameField.set(obj, value); obj : 要设置值字段对应的对象 value :具体指*/field.set(n,"fewwwfeg");//5.获取指定名称的和访问权限无关的字段

Field emailField = clz.getDeclaredField("email");//5.1 设置忽略访问权限

emailField.setAccessible(true);//5.2 设置私有字段的值

emailField.set(n, "xln@qq.com");

System.out.println(n);

}}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值