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

黑马程序员——Java基础 ---反射

2015-11-30 22:54 246 查看
------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------

[b] 反射[/b]

一:类的加载

A:类的加载概述

系统在运行程序的时候,会把.class文件加载到内存中,而编译期不会加载。。

1,当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过

加载,连接,初始化三步来实现对这个类进行初始化。

1)加载:

就是指将class文件读入内存,并为之创建一个Class对象,任何类被

使用时系统都会建立一个Class对象。

2)连接:

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

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

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

3)初始化:

就是我们以前的初始化步骤

B:类的加载时机

1,创建类的实例

2,访问类的静态变量,或者为静态变量赋值 Person.country =”中国”;

3,调用类的静态方法 Person.show( );

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

5,初始化某个类的子类 Fu Zi

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

二:类的加载器

A:类的加载器的概述

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

虽然我们不需要关心类加载机制,但是了解这个机制我们就能

更好的理解程序的运行。

B:类加载器的分类

Bootstrap ClassLoader 根类加载器

Extension ClassLoader 扩展类加载器

Sysetm ClassLoader 系统类加载器

C:类加载器的作用

1,Bootstrap

Bootstrap ClassLoader 根类加载器

也被称为引导类加载器,负责java核心类的加载

比如:System,String等,在JRE的lib目录下rt.jar文件中

2,Extension

Extension ClassLoader 扩展类加载器

负责JRE的扩展目录中jar包的加载

在JDK中JRE的lib目录下ext目录

3,Sysetm

Sysetm ClassLoader 系统类加载器

负责在JVM启动时加载来自java命令的class文件

以及classpath环境变量所指定的jar包和类路径

三:反射

A:反射的概述

1,java反射机制是在运行状态中

对于任意一个类,都能够知道这个类的所有属性和方法。

对于任意一个对象,都能够调用它的任意一个方法和属性。

2,这种动态(运行时)获取的信息以及动态调用对象的方法的功能称为

Java语言的反射机制。(反向的获取和调用)

B:反射机制的作用

1,反编译:.class-->.java

2,通过反射机制访问java对象的属性,方法,构造方法等;

C:反射机制中的类

java.lang.Class;

java.lang.reflect.Constructor; java.lang.reflect.Field;

java.lang.reflect.Method;

java.lang.reflect.Modifier;

Class对戏那个可以获得该类里的方法, 构造器和Field, 这三个累都位于java.lang.reflect包下, 并实现了java.lang.reflect.Member接口.

创建对象

通过反射生成对象的两种方式:

使用Class对象的newInstance()方法. 需要Class对象对应的类有默认构造器, 儿执行newInstance()方法就是利用默认构造器创建该类的实例.

使用Class对象获得指定的Constructor对象, 再调用Constructor对象的newInstructor()方法创建该Class对象对应类的实例.

调用方法

1,通过Class对象的getMethods()或getMethod()方法能获得全部或指定方法.

2,Method类有个invoke()方法, 用以调用指定对象的方法:
Object invoke(Object obj, Object... args): obj是执行该方法的主调, args是执行时传入该方法的实参.

3,当通过Method的invoke()方法调用对应方法时, Java会要求程序必须有调用该方法的权限. 如果程序需要调用private方法, 可以先调用Method对戏那个的setAccessible方法:
setAccessible(boolean flag): true表示该Method在使用时应该取消访问权检查, false表示要检查.

4,setAccessible()方法继承自Method的父类AccessibleObject, Constructor和Field类也可以调用该方法.

访问属性值

1, 通过Class对象的getFields()或getField()方法能获得全部或指定Field.

2,Field类量两个方法:

getXxx(Object obj): 获取obj对象该Field的属性值. 此处Xxx对应8个基本类型, 如果该属性的类型是引用类型, 则取消get后面的Xxx.

setXxx(Object obj, Xxx val): 将obj对象的该属性值设为val. 此处Xxx对应8个基本类型, 如果该属性的类型是引用类型, 则取消get后面的Xxx.

操作数组

1, java.lang.reflect包下还提供了一个Array类, Array对象可以代表所有的数组. 程序可以通过Array动态地创建数组, 操作数组元素.

2,Array的方法:

static Object newInstance(Class<?> componentType, int... length): 创建一个据有偶指定的元素类型, 指定维度的新数组.

Static xxx getXxx(Object array, int index): 返回array数组中的第index个元素. 如果数组元素是引用类型, 则该方法变为get(Object array, int index).

static void setXxx(Object array, int index, xxx val): 将array数组的第index个元素设为val. 如果数组元素是引用类型, 则该方法变为get(Object array, int index, xxx val).

D:具体功能实现

例(1)

1.获取.class文件的对象
2.调用该对象方法 newInstance

public class Demo1_Constructor {
@SuppressWarnings("unchecked")
public static void main(String[] args) throws Exception {

// 1 获取.class对象
Class clz = Class.forName("cn.itcast_bean.User");

// 2.调用方法 , 获取有参的构造 ,就需要传递对应参数 .
Constructor constructor = clz.getConstructor(String.class, int.class);

Object u = constructor.newInstance("悟空", 800);

System.out.println(u);

User user = new User("三藏", 500);

System.out.println(user);

}
20}


例(2)

1.获取.class文件的对象
2.调用该对象方法 getFiled

Field
Object get(Object obj) 返回指定对象上此 Field 表示的字段的值

public class Demo2_Filed {
public static void main(String[] args) throws Exception {
// 1 获取.class对象
Class clz = Class.forName("cn.itcast_bean.User");

User u1 = new User("悟空", 800);
User u2 = new User("三藏", 500);
// 2.调用方法
Field field = clz.getField("id"); // 把id字段 变成 Filed对象
Object object = field.get(u1); // 获取某一个对象的该字段的值
System.out.println(object);

// 获取 age
Field field2 = clz.getDeclaredField("age"); // 暴力获取
field2.setAccessible(true);  // 打开权限
Object object2 = field2.get(u2); // 获取 字段 值
System.out.println(object2);

}
}


例(3)

1.定义 User 类
2.Class.forName( ".....");
3.Method m = clz.getMethod();
4.执行

public class Demo3_Method {
@SuppressWarnings("unchecked")
public static void main(String[] args) throws Exception {
// 获取 .class文件的对象

Class clz = Class.forName("cn.itcast_bean.User");
// 创建出来 对象
User u1 = new User("悟空", 800);
// 获取 Method 对象
Method m = clz.getMethod("run"); // run 就是 方法名字 , 后面的 就是 run 方法的参数 ,没有参数
// 就 不传

// m.invoke(new User());// 运行 run
m.invoke(u1); // 运行 u1的 run

// 获取私有方法
Method sleep_method = clz.getDeclaredMethod("sleep");
sleep_method.setAccessible(true);
sleep_method.invoke(u1);

}
}


例(4)

ArrayList<String> 添加一个数字

public class Demo4_Generic {
@SuppressWarnings("unchecked")
public static void main(String[] args) throws Exception {
ArrayList<String> al = new ArrayList<>();

al.add("aaa");
al.add("bbb");
al.add("ccc");
al.add("dd");

// al.add(123); // 通过泛型 ,来限制你存储 .但是 泛型这个 东西 ,在.class文件 ,会被擦除 .
System.out.println(al);

// 通过反射技术 ,往 al 添加 123
// 获取 .class 文件对象
// Class.forName("java.util.ArrayList");
Class clz = al.getClass();

// 获取 add 方法的method 对象
Method add_mehtod = clz.getDeclaredMethod("add", Object.class);
add_mehtod.setAccessible(true);

// method对象 invoke
add_mehtod.invoke(al, 123);
System.out.println(al);
}
}


------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: