黑马程序员_java反射总结

---------android培训、java培训期待与您交流! ---------

Java反射机制
概念:
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个
类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个
方法;这种动态获取的信息以及动态调用对象的方法的功能称为java
语言的反射机制。 
作用:
Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所
属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类
所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成
动态代理。 
初步认识反射:
Object类:
getClass方法:
public final Class<?> getClass()
所有类的队形都可以使用getClass()方法,此方法返回的是一个class,
可以通过class进行反射操作。
代码:
package com.fanshe.test01;
class Person{

}
public class PersonTest {
public static void main(String[] args) {
Person per=new Person();
System.out.println(per.getClass().getName());
}


}
结果:返回一个对象所属的包名加类名
认识class类:
在反射机制中,class类是操作的源头,所有的反射操作从此类开始,
Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以
及通过调用类加载器中的 defineClass 方法自动构造的。
要想实例化此类对象,有三种形式:
1.  Object类:getClass方法:public final Class<?> getClass()
2. 通过.class的形式
3. 通过class类的静态方法 
代码实例:
验证第一种方式,
class Person{
}
public class PersonTest {
public static void main(String[] args) {
Person per=new Person();
Class<?>c= per.getClass();  //?代表通配符
System.out.println(c.getName());
}
}


验证第二种方式:
class Person{
}
public class PersonTest {
public static void main(String[] args) {
Class<?>c= Person.class;
System.out.println(c.getName());
}
}
验证第三种方式:
class Person{
}
public class PersonTest {
public static void main(String[] args) {
Class<?> c=null;
try {
c = Class.forName("com.fanshe.test01.Person");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(c.getName());
}
}
虽然有三种方法,最常用的是第三种forName(),其次就是.class
通过class类实例化对象
1.实例化无参构造的People类,此类重写toString()方法。
代码:
People类:
package com.fanshe.test01;
public class People {
public String toString(){
return "hello world";
}
}
 PeopleTest类:
public class PeopleTest {
public static void main(String[] args) {
try {
Class<?>c=Class.forName("com.fanshe.test01.People");
People p=(People)c.newInstance();
System.out.println(p);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
输出结果为hello world 因为People类重写了toString方法。
2.实例化有指定构造方法的People类,此类重写toString()
方法。
API内重要方法:
java.lang.reflect 
类 Constructor<T>
java.lang.Object
类型参数:
T- 在其中声明构造方法的类。


getConstructors
public Constructor<?>[] getConstructors()
                                 throws SecurityException
返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 
对象所表示的类的所有公共构造方法。如果该类没有公共构造方法,
或者该类是一个数组类,或者该类反映一个基本类型或 void,则返
回一个长度为 0 的数组。
若此对象包含很多个有参构造方法,返回的第一个也就是数组下标值
是0的那个构造方法就是带参数最多的那个。
具体实现步骤:
1.通过class.forname实例化一个带有有参构造方法的类
2.Constructor<?> con[]=c.getConstructors(); 通过API内的方法,取得
此类的所有的构造方法。
3.Con【0】的就是带有参数最多的那一个有参构造方法,其次通过 
con[0].newInstance("mmm",19);实例化此类,并给有参构造赋值。
4.最后强转,因为实例化后得到是一个object类型的对象,要向下转
型,People p1=(People) con[0].newInstance("mmm",19);最后打印p的
值,若能输出hello world则证明成功,因为重写了toString方法,所
以可以打印hello world。
实例代码:
People类:
package com.fanshe.test02;
public class People {
private String name;
private int age;
public People(String name,int age){
this.setName(name);
this.setAge(age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String toString(){
return "hello world";
}
}
TestPeople类:
package com.fanshe.test02;
import java.lang.reflect.Constructor;
public class TestPeople {
public static void main(String[] args) throws Exception {
Class<?> c=Class.forName("com.fanshe.test02.People");
Constructor<?> con[]=c.getConstructors();
People p1=(People) con[0].newInstance("mmm",19);
System.out.println(p1);
}
}
3.通过class类取得完整结构
1.取得People类的父类
   1.1API内方法:
getSuperclass
public Class<? super T> getSuperclass()
返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。如果
此 Class 表示 Object 类、一个接口、一个基本类型或 void,则返回 null。如果此对象
表示一个数组类,则返回表示该 Object 类的 Class 对象。 
返回:
此对象所表示的类的超类。


实例代码:
package com.fanshe.test03;
import java.lang.reflect.Constructor;
public class TestPeople {
public static void main(String[] args) throws Exception {
Class<?> c=Class.forName("com.fanshe.test03.People");
Class<?> sc=c.getSuperclass();
System.out.println(sc.getName());
}
}
注释:用class.forname去实例化People类,People类在这里就不给
出了,People类继承自object类。打印结果为java.lang.object


2.取得People类的全部接口
   2.2API的方法:
getInterfaces
public Class<?>[] getInterfaces()
确定此对象所表示的类或接口实现的接口。 
如果此对象表示一个类,则返回值是一个数组,它包含了表示该类所实现的所有接口的对象。
数组中接口对象顺序与此对象所表示的类的声明的 implements 子句中接口名顺序一致
返回值:该类所实现的接口的一个数组。
实例代码:
package com.fanshe.test03;
import java.lang.reflect.Constructor;
public class TestPeople {
public static void main(String[] args) throws Exception {
Class<?> c=Class.forName("com.fanshe.test03.People");
Class<?> sc[]=c.getInterfaces();
for(int i=0;i<sc.length;i++){
System.out.println(sc[i].getName());
}
}
}
3.取得People类中全部的构造方法
 3.1 API方法:


  java.lang.Class<T>


getModifiers
public int getModifiers()
返回此类或接口以整数编码的 Java 语言修饰符。修饰符由 Java 虚拟机的 public、
protected、private、final、static、abstract 和 interface 对应的常量组成;它们应当使用 
Modifier 类的方法来解码。
返回:
表示该类修饰符的 int






java.lang.reflect.Constructor<T>


getParameterTypes
public Class<?>[] getParameterTypes()
按照声明顺序返回一组 Class 对象,这些对象表示此 Constructor 对象所表示构造方法
的形参类型。如果底层构造方法不带任何参数,则返回一个长度为 0 的数组。 
返回:
此对象表示的构造方法的参数类型


java.lang.reflect.Modifier


toString
public static String toString(int mod)
返回描述指定修饰符中的访问修饰符标志的字符串


实例代码:
package com.fanshe.test04;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
@SuppressWarnings("unused")
public class TestPeople {
public static void main(String[] args) throws Exception {
Class<?> c=Class.forName("com.fanshe.test04.People");//实例化
People类
Constructor<?> con[]=c.getConstructors();//得到所有的构造方

for(int i=0;i<con.length;i++){//遍历构造方法
int mod=c.getModifiers();//获得修饰符
String str=Modifier.toString(mod);//还原修饰符
Class<?> parm[]=con[i].getParameterTypes();//或得参数列表
System.out.print(str+" ");//打印出构造方法内内的修饰符
System.out.print(con[i].getName()+"(");
for(int x=0;x<parm.length;x++){//遍历出参数
System.out.print(parm[x].getName()+" "+"arg-"+x);//获取
每个参数的名字
if(x<parm.length-1){
System.out.print(",");
}
}
System.out.println(")");

}
}
}
4.取得一个类的全部方法
4.1API内方法:
java.lang.Class<T>


getMethods
public Method[] getMethods()
                    throws SecurityException
返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口
(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 
member 方法。


实例代码:
package com.fanshe.test03;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class TestPeople {
public static void main(String[] args) throws Exception {
Class<?> c=Class.forName("com.fanshe.test03.People");
Method sc[]=c.getMethods();
for(int i=0;i<sc.length;i++){
System.out.println(sc[i].getName());
}
}
}
5.取得一个类的全部属性
5.1 api内方法:
java.lang.Class<T>


得到继承而来的公共属性:
getFields
public Field[] getFields()
                  throws SecurityException
返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的
所有可访问公共字段。
返回:
表示公共字段的 Field 对象的数组






java.lang.Class<T>




getDeclaredMethods
public Method[] getDeclaredMethods()
                            throws SecurityException
返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有
方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。


返回:
表示此类所有声明方法的 Method 对象的数组
实例代码:
public class TestPeople {
public static void main(String[] args) throws Exception {
Class<?> c=Class.forName("com.fanshe.test03.People");
Field f[]=c.getDeclaredFields();
for(int i=0;i<f.length;i++){
String mod=Modifier.toString(f[i].getModifiers());//获取修饰

System.out.println(mod+" ");
System.out.println(f[i].getType().getName());
}
}
}




6.调用另一个类的方法(重点)
   6.1调用一个类的无参返回值为void的方法
   6.2 API内的方法:
   
  java.lang.Class<T>


  getMethod
  public Method getMethod(String name,
                        Class<?>... parameterTypes)
                 throws NoSuchMethodException,
                        SecurityException
返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
name 参数是一个 String,用于指定所需方法的简称。parameterTypes 参数是按声明顺
序标识该方法形参类型的 Class 对象的一个数组。
  返回:
与指定的 name 和 parameterTypes 匹配的 Method 对象
方法中的参数Class... parameterTypes怎么理解 ?
name 是要获得类对象的方法名;
Class... parameterTypes 是一个name方法的参数数组(无参方法不写,有几个参数就定多长的数组);
例如 :
public class Test {
     public String doPrint(String s,int i,Object o)
    {
    }
}
这是一个具有3个参数的方法  要获得他的反射方法 应该这样写。
Class cls = Class.forName(Test.class); 
Class[] cl = new Class[3];//3是参数个数
cl[0] = String.class;
cl[1] = int.class;
cl[2] = Object.class;
Method m = cls.getDeclaredMethod("doPrint",cl);


这个m 就是用反射获得的方法


java.lang.reflect.Method


  invoke
  public Object invoke(Object obj,
                     Object... args)
              throws IllegalAccessException,
                     IllegalArgumentException,
                     InvocationTargetException
对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。个别参数被自动解
包,以便与基本形参相匹配,基本参数和引用参数都随需服从方法调用转换。


  如果底层方法是静态的,那么可以忽略指定的 obj 参数。该参数可以为 null。
  如果底层方法所需的形参数为 0,则所提供的 args 数组长度可以为 0 或 null。
  参数:
obj- 从中调用底层方法的对象
args- 用于方法调用的参数
  返回:
使用参数 args 在 obj 上指派该对象所表示方法的结果


   实例代码:
   People1类的代码:
package com.fanshe.test04;
public class People01  {
private String name;
private int age;
public People01(){
}
public People01(String name){
this.setName(name);
}
public People01(String name,int age){
this.setName(name);
this.setAge(age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void say(){
System.out.println("hello world");
}
}
使用反射调用People1的say方法:
package com.fanshe.test04;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
@SuppressWarnings("unused")
public class TestPeople01 {
public static void main(String[] args) throws Exception {
Class<?> c=Class.forName("com.fanshe.test04.People01");//实例
化People类
Method m=c.getMethod("say");
m.invoke(c.newInstance() );//打印出的值为 hello world
}
}
6.2调用另一类的有返回值,有参数列表的方法。
例子:调用People类中的say方法,此方法带有String类型的返回值,
和String name,int age等参数。


实例代码:
People类代码:
package com.fanshe.test04;
public class People02  {
private String name;
private int age;
public People02(){

}
public People02(String name){
this.setName(name);
}
public People02(String name,int age){
this.setName(name);
this.setAge(age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String say(String name,int age){
return name+"是"+age+"岁";
}
}
实例化people类:
package com.fanshe.test04;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
@SuppressWarnings("unused")
public class TestPeople02 {
public static void main(String[] args) throws Exception {
Class<?> c=Class.forName("com.fanshe.test04.People02");//实例
化People类
Method m=c.getMethod("say",String.class,int.class);//指明操作
的类型
String value=(String)m.invoke(c.newInstance() ,"扽哇",20);//传
入底层的对象(既people类的对象)和参数
System.out.println(value);
}
}
7.1调用另一个类的getter和setter方法:
思路:
1.有一个javabean,内有getter和setter方法
2.通过反射找到该类,并通过Stirng类的方法,把它的首字母给大写。
具体代码:
package zz.person;


class Person {
private String name;
private int age;
public String getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return this.age;
}
public String toString(){
return "姓名:" + this.name + "\n年龄:" + this.age;
}
}  


实例化类:
package zz.invokesetgetdemo;
import java.lang.reflect.Method;


public class InvokeSetGetDemo{
public static void main(String []args){
Class<?> c = null;
Object obj = null;
try{
c = Class.forName("zz.Person");
}catch (ClassNotFoundException e){
e.printStackTrace();
}
try {
obj = c.newInstance();
}catch (InstantiationException e){
e.printStackTrace();
}catch (IllegalAccessException e){
e.printStackTrace();
}
setter(obj, "name", "张泽", String.class);
setter(obj, "age", 18, int.class);
System.out.print("姓名:");
getter(obj, "name");
System.out.print("年龄:");
getter(obj, "age");
}


/*
*@param obj 操作的对象
*@param att 操作的属性
*@param value 设置的值
*@param type 参数的类型
*/
public static void setter(Object obj, String att, Object value, 
Class<?>type){
try {
Method met = obj.getClass().
getMethod("set" + initStr(att), type);
met.invoke(obj, value);
}catch (Exception e){
e.printStackTrace();
}
}
public static void getter(Object obj, String att){
try {
Method met = obj.getClass().getMethod("get" + initStr(att));
System.out.println(met.invoke(obj));
}catch (Exception e){
e.printStackTrace();
}
}
public static String initStr(String old){// 将单词的首字母大写
String str = old.substring(0,1).toUpperCase() + old.substring(1) ;
return str ;
}
}
8.通过反射操作另一个类的属性
实例代码:
People类:
package com.fanshe.test05;
public class People02  {
private String name;
private int age;
public People02(){
}
public People02(String name){
this.setName(name);
}
public People02(String name,int age){
this.setName(name);
this.setAge(age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String toString(){
return name.toString();//重写了toString方法
}
}
实例化People类:
package com.fanshe.test05;
import java.lang.reflect.Field;
public class TestPeople {
public static void main(String agrs[]){
try {
Class<?>c=Class.forName("com.fanshe.test05.People02");
Object o=c.newInstance();
Field f=c.getDeclaredField("name");
f.setAccessible(true);
f.set(o, "yu");
System.out.println(o);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
---------android培训、java培训期待与您交流! ---------





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值