您的位置:首页 > 职场人生

黑马程序员 JAVA提高——反射

2013-12-02 18:33 393 查看
----------- android培训java培训、java学习型技术博客、期待与您交流! ------------

java中的反射机制

一:什么是反射?

1,反射的概念:主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。反射本身并不是一个新概念,尽管计算机科学赋予了反射概念新的含义。在计算机科学领域,反射是指一类应用,它们能够自描述和自控制。也就是说,这类应用通过采用某种机制来实现对自己行为的描述(self-representation)和监测(examination),并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。

2,java中的类反射:
反射是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查。

反射是 Java 被视为动态(或准动态)语言的关键,允许程序于执行期 反射API 取得任何已知名称之 class 的內部信息,包括 package、type parameters、superclass、implemented interfaces、inner classes, outer class, fields、constructors、methods、modifiers,並可于执行期生成实例、变更 字段內容或唤起 方法。

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

一句话:java反射就是将类中的各个成分映射称为java类。

了解了反射的基本概念后,我们就要走进java反射,首先介绍反射的基石——Class类

二,Class类——反射的基石

java中万事万物皆为对象,那么在java中各种各样的java类又是不是一个对象呢,答案是肯定的。就是Class类。

具体来说:Class对象就是用来描述,那么描述类的那些属性呢。描述类的成员变量,方法,够着函数,及各种修饰符等等信息。

一句话Class对象就是用来描述java中类的信息的一种特殊的类。

注意:与class的区别,class是java中的关键字,而Class是java中的一个类。不要混淆

下面通过代码和注释简要说明下Class

package cn.itcast.day1;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

public class ReflectTest {
public static void main(String[] args) throws Exception {
String str1 = "abc";
//获取Class对象的三种方法
  Class cls1 = str1.getClass();
Class cls2 = String.class;
Class cls3 = Class.forName("java.lang.String");
//Class代表类的字节码文件,在内存中只有一份
 System.out.println(cls1 == cls2);
System.out.println(cls1 == cls3);

System.out.println(cls1.isPrimitive());//判断是不是基本类型
System.out.println(int.class.isPrimitive());
System.out.println(int.class == Integer.class);
System.out.println(int.class == Integer.TYPE);
System.out.println(int[].class.isPrimitive());
System.out.println(int[].class.isArray());//判断是不是数组
}
}

三:反射的应用

1.java反射--Constructor

首先介绍一下Constructor类,这个类用来封装反射得到的构造器,Class有四个方法来获得Constructor对象

public
Constructor<?>[] getConstructors()      返回类中所有的public构造器集合,默认构造器的下标为0

public
Constructor<T> getConstructor(Class<?>... parameterTypes)
  返回指定public构造器,参数为构造器参数类型集合

public
Constructor<?>[] getDeclaredConstructors()  返回类中所有的构造器,包括私有

public
Constructor<T> getDeclaredConstructor(Class<?>...
parameterTypes) 返回任意指定的构造器


package cn.itcast.day1;

import java.lang.reflect.Constructor;

class Person{
private String name;
private int age;

public Person(){
System.out.println("共有的空的构造函数");
}
private Person(String name){
this.name = name ;
System.out.println("私有的构造器");
}
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;
}
@Override
public String toString() {

return this.name+"....."+this.age;
}

}

public class Test {

public static void main(String[] args) throws Exception {
method();

}

private static void method() throws Exception{
Person p = new Person();
Class cls1 = p.getClass();
// 获取构造方法Constructor
// getConstructor() only for public
// getDeclaredConstructor() global access all

//指定参数列表获取特定的方法
Constructor con = cls1.getDeclaredConstructor(String.class);
con.setAccessible(true); //设置可访问的权限,暴力反射,强行的使用私有的构造器
Object obj = con.newInstance("zhangsan");
System.out.println(obj); //打印一下这个对象的信息

//获取所有的构造方法集合,返回构造器的数组
Constructor con1[] = cls1.getDeclaredConstructors();
System.out.println(con1.length);
}

}

注意:

a:   获取构造方法Constructor中 getConstructor()和 getDeclaredConstructor()  的区别:

前者只是获取共有的构造器,而后者可以获取私有的构造器,当然需要:  con.setAccessible(true); //设置可访问的权限

b:newInstance()用来调用空的构造函数来实例化变量。否则的话就要传入相应的参数。

2,java反射——Field

 了解了构造器,其实你可以猜到成员变量的获取方法了,成员变量用Field类进行封装。

       主要的方法非常的类似:
public
Field getDeclaredField(String name)  获取任意指定名字的成员[/b]
public
Field[] getDeclaredFields()             获取所有的成员变量

public
Field getField(String name)           获取任意public成员变量

public
Field[] getFields()                          获取所有的public成员变量

代码说明:
private static void method_1() throws Exception {
/**
* 获取成员变量Field
* getField()
* getDeclaredField()
* */
Person p = new Person();
Class cls1 = p.getClass();
Field field = cls1.getDeclaredField("name");
field.setAccessible(true);
System.out.println((String)field.get(p));

Field[] fields = cls1.getDeclaredFields();
for (Field f : fields){
System.out.println(f.getName());
}
}


分析:对比Constructor的学习,同理的

有一点注意:你要调用对象的字段,所以你要传入你要调用那个对象,这是很显然的。

2,java反射——Method

轻车熟路:同理先看Methodde 构造器:

public
Method[] getMethods()    获取所有的共有方法的集合

public
Method getMethod(String name,Class<?>... parameterTypes)
获取指定公有方法 参数1:方法名 参数2:参数类型集合  

public
Method[] getDeclaredMethods()  获取所有的方法

public
Method getDeclaredMethod(String name,Class<?>... parameterTypes)
获取任意指定方法

代码案例:

private static void method_2() throws Exception {
/**
* 调用类的方法 Method
* getMethod()
* getDeclaredMethod()
*
* */
Person p = new Person();
Class cls1 = p.getClass();
Method f = cls1.getMethod("getName", null);
Object name = f.invoke(p, null);
System.out.println((String)name);

Method[] methods = cls1.getDeclaredMethods();

for(Method method : methods){
System.out.println(method.getName());
}

}
总结:要想调用一个method实例,很容易的想到,要传给一个对象,即要调用那个对象的方法,自然还要传入,形参。
问题?若果一个方法伪静态的,不需要对象则传入null;







PS:反射的其他细节会在以后的博文中介绍

---- ASP.Net+Android+IOS开发.Net培训、期待与您交流!--------详细请查看:http://edu.csdn.net------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息