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

黑马程序员--反射的“魅力”

2015-12-22 11:24 471 查看
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

第一讲    类加载器和反射

一、类的加载

   当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。

    加载

    •就是指将class文件读入内存,并为之创建一个Class对象。

    •任何类被使用时系统都会建立一个Class对象。

    连接

    •验证 是否有正确的内部结构,并和其他类协调一致

    •准备 负责为类的静态成员分配内存,并设置默认初始化值

    •解析 将类的二进制数据中的符号引用替换为直接引用

    初始化

二、类初始化时机    

    •创建类的实例

    •访问类的静态变量,或者为静态变量赋值

    •调用类的静态方法

    •使用反射方式来强制创建某个类或接口对应的java.lang.Class对象

    •初始化某个类的子类

•直接使用java.exe命令来运行某个主类

三、类加载器

1、类加载器

•负责将.class文件加载到内在中,并为之生成对应的Class对象。

•我们虽然不需要关心类加载机制,但是了解这个机制我们就能更好的理解程序的运行。

2、类加载器的组成

(1)Bootstrap ClassLoader 根类加载器

根类加载器也被称为引导类加载器,负责Java核心类的加载,比如System,String等。在JDK中JRE的lib目录下rt.jar文件中

(2)Extension ClassLoader 扩展类加载器

扩展类加载器负责JRE的扩展目录中jar包的加载。在JDK中JRE的lib目录下ext目录

(3)Sysetm ClassLoader 系统类加载器

系统类加载器负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径(我们自己写的东西就是用这个加载的)

四、反射

1、反射的定义

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

2、反射的实现

学习反射之前我们要使用类的成员变量、构造方法、成员方法是这样使用的(示例)
学习了反射之后,我们就要通过class文件对象,去使用该类中的成员变量,构造方法,成员方法。要想这样使用,首先必须得到class文件对象,其实也就是Class类的对象。所有的.class文件都是Class类的对象。同时,类中的成员变量、构造方法、成员方法也都变成了一个类
•成员变量   Field
•构造方法   Constructor
•成员方法  Method
通过以上这三个类的对象调方法去使用该方法(或该变量)即为反射。
3、各类的方法解析
(1)   获取Class类对象的方法
public static Class
forName(String className)
静态方法通过Class类直接调用,参数是类的名称(注意:这里的类名必须为全路径),建议括号外写类路径,由于有提示不会出现书写错误,再将类全路径复制到相应位置。
(2)   获取Constructor类对象的方法
public Constructor [] getConstructors()

返回所有公共构造方法(用public修饰的)

 

        public Constructor [] getDeclaredConstructors()

        获取所有的构造方法包括私有的构造方法

 

        public Constructor getConstructor

       (Class<?>... parameterTypes)

        例如:public Constructor getConstructor

       (int.class,String.class)

        获取单个带参构造方法对象,参数为可变参数,因为构造方法可能没有参数、或者有一个参数、或者有多少个参数。(不能获取私有构造器)

 

public Constructor getDeclaredConstructor

(Class<?>... parameterTypes)

        public void setAccessible(boolean flag)

        获取单个带参构造方法对象,参数为可变参数,因为构造方法可能没有参数、或者有一个参数、或者有多少个参数。(可以获取私有构造器)但是需要取消访问检查。

(3)   通过Constructor类对象的方法创建示例对象
public Object newInstance()

返回这个类的示例化对象,他的类型是Object,但是他的本质还是原来的类型,是原来类的对象,所以可以使用强制类型转换转回到原来的类型。

(4)获取Field类对象的方法
        public Field[] getFields()

返回所有公共成员变量(用public修饰的)

 

        public Field [] getDeclaredFields ()

        获取所有的成员变量包括私有的成员变量

 

        public Field getField(String name)

        获取单个成员变量(不包括私有的成员变量)

 

        public Field getDeclaredField(String name)

        public void setAccessible(boolean flag)

         获取单个成员变量(包括私有成员变量),参数为该成员变量名,但是需要取消访问检查。

 

public Constructor getDeclaredConstructor()

public Object newInstance()

        public void set(Object obj, Object value)

        先通过无参构造创建对象,然后再调用该方法给成员变量赋值

        

(4)   获取Method类对象的方法(不再赘述)
获取所有方法

getMethods

获取自己的包括父亲的公共方法

 

getDeclaredMethods

获取自己的不包括父亲的所有方法

 

获取单个方法

getMethod

getDeclaredMethod

4、使用步骤

A:获取类的字节码文件对象

B:用Class对象调用方法创建Constructor

      	--Constructor对象调用方法创建实例对象

   用Class对象调用方法创建Field

      	--使用B步骤创建实例对象

--Field对象调用方法(set方法)以上一步实例对象为参数给成员变量赋值

   用Class对象调用方法创建Method

      	--使用B步骤创建实例对象

        --Method对象调用方法(invoke方法)以上一步实例对象为参数(其余参数为原方法的实际参数)调用方法

五、代码实现

学生类
package cn.itcast_01;

public class Student {
public String name;
int age;
private char sex;

private Student() {
super();
}

Student(String name) {
super();
this.name=name;
}

public Student(String name, int age, char sex) {
super();
this.name = name;
this.age = age;
this.sex = sex;
}

public void show(){
System.out.println("show");
}

private void method(){
System.out.println("method");
}

public String study(String name){
return name+"爱学习";
}

@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", sex=" + sex + "]";
}

}<textarea readonly="readonly" name="code" class="java"><br/>

1、反射创建实例对象

示例
package cn.itcast_01;

import java.lang.reflect.Constructor;

public class ConstructorDemo {
public static void main(String[] args) throws Exception {
Class c=Class.forName("cn.itcast_01.Student");

Constructor[] cons=c.getConstructors();
for(Constructor constructor: cons){
System.out.println(constructor);
//public cn.itcast_01.Student(java.lang.String,int,char)
}

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

Constructor[] cons1=c.getDeclaredConstructors();
for(Constructor constructor:cons1){
System.out.println(constructor);
/*public cn.itcast_01.Student(java.lang.String,int,char)
cn.itcast_01.Student(java.lang.String)
private cn.itcast_01.Student()*/
}

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

Constructor con=c.getDeclaredConstructor();
con.setAccessible(true);
Object obj=con.newInstance();
System.out.println(obj);
//Student [name=null, age=0, sex= ]

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

Constructor con1=c.getDeclaredConstructor(String.class);
Object obj1=con1.newInstance("刘亦菲");
System.out.println(obj1);
//Student [name=刘亦菲, age=0, sex= ]

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

Constructor con2=c.getConstructor(String.class, int.class, char.class);
Object obj2=con2.newInstance("刘亦菲",27,'女');
System.out.println(obj2);
//Student [name=刘亦菲, age=27, sex=女]

}
}<textarea readonly="readonly" name="code" class="java">


2、反射给成员变量赋值

示例
package cn.itcast_01;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.jar.Attributes.Name;

public class FieldDemo {
public static void main(String[] args) throws Exception {
Class c=Class.forName("cn.itcast_01.Student");
Constructor con=c.getConstructor(String.class,int.class,char.class);
Object obj=con.newInstance("刘亦菲",27,'女');
Field[] field=c.getFields();
for(Field f:field){
System.out.println(f);
//public java.lang.String cn.itcast_01.Student.name
}

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

Field[] field2=c.getDeclaredFields();
for(Field f:field2){
System.out.println(f);
/*public java.lang.String cn.itcast_01.Student.name
int cn.itcast_01.Student.age
private char cn.itcast_01.Student.sex*/
}

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

Field field3=c.getField("name");
field3.set(obj, "林心如");
System.out.println(obj);
//Student [name=林心如, age=27, sex=女]

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

Field field4=c.getDeclaredField("age");
field4.set(obj, 18);
System.out.println(obj);
//Student [name=林心如, age=18, sex=女]

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

Field field5=c.getDeclaredField("sex");
field5.setAccessible(true);
field5.set(obj, '男');
System.out.println(obj);
//Student [name=林心如, age=18, sex=男]

}
}<textarea readonly="readonly" name="code" class="java">


3、反射调用成员方法

示例
package cn.itcast_01;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class MethodDemo {
public static void main(String[] args) throws Exception {
Class c = Class.forName("cn.itcast_01.Student");
Constructor cons = c.getConstructor(String.class, int.class, char.class);
Object obj = cons.newInstance("刘亦菲", 27, '女');

Method[] methods = c.getMethods();
for(Method m:methods){
System.out.println(m);
}

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

Method[] methods2 = c.getDeclaredMethods();
for(Method m:methods2){
System.out.println(m);
}

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

Method methods3=c.getMethod("show");
methods3.invoke(obj);
//show

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

Method methods4=c.getDeclaredMethod("method");
methods4.setAccessible(true);
methods4.invoke(obj);
//method

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

Method methods5=c.getMethod("study",String.class);
Object obj1=methods5.invoke(obj,"刘亦菲");
System.out.println(obj1);
//刘亦菲爱学习
}
}<textarea readonly="readonly" name="code" class="java">

 

 

 

 
 

 

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: