黑马程序员_高新技术2(Class类,反射Reflect(重点知识))
来源:互联网 发布:中国人口老龄化数据图 编辑:程序博客网 时间:2024/05/17 04:47
-------android培训、java培训、期待与您交流! ----------
一.Class类
1.反射的基石:Class类
1)java程序中的各个java类属于同一类事物,描述这类事物的java类名就是Class.
2)对比提问:众多的人用一个什么类表示?众多的java类用一个什么类表示?
人-->Person
Java类-->Class
3)对比提问:Person类代表人,它的实例对象就是张三,李四这样一个个具体的人,Class
类代表Java类,它的各个实例对象又分别对应什么呢?
<1>对应各个类在内存中的字节码,例如:Person类的字节码,ArrayList类的字节码,等等。
<2>一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,
<3>不同的类的字节码是不同的,所以它们在内存中的内容是不同的,这一个个空间可分别用一个个
的对象来表示,这些对象显然具有相同的类型,这个类型是什么呢?
4)如何得到各个字节码对应的实例对象(Class类型)
<1>类名.class,例如:System.class
<2>对象.getClass(),例如:new Date().getClass()
<3>Class.forName("类名"),例如:Class.forName("java.util.Date")//查询或加载
2.class与Class的区别:
class是指java类,java类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性的值是什么,则由这个类的实例对象来确定,不同的实例对象有不同的属性值。
java程序中的各个类,也属于同一类事物,Class类是用来描述java程序中的各个java类这一事物的,Class类描 述了类的名字,类的访问属性,类所属的包名,字段名称的列表,方法名称的列表等等。
3.Class.forName("java.lang.String");中forName()的作用:
返回字节码。有两种方式:第一,字节码已加载过。第二,字节码未被加载过,在java虚拟机中还不存在,
则用类加载器去加载,然后缓存到虚拟机中,以后就不用再加载了。
二.反射概念
反射就是把Java类中的各种成分映射成相应的java类。例如,一个java类可用一个Class类的对象来
表示,一个类中的组成部分有:成员变量,方法,构造方法,包等等信息也可用一个个的java类来
表示,就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个类。表示java类的Class类显然
要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用
相应类的实例对象来表示,它们是Field,Method,Contructor,Package等等。
一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法
可以得到这些实例对象。然后再使用这些对象。
三.构造方法的反射应用
1)Constructor类代表某个类中的一个构造方法。
2)得到某个类所有的构造方法:
例子:Constructor[] contructors = Class.forName("java.lang.String").getConstructors();
3)得到某一个构造方法:
例子:Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class);
//获取方法时要用到类型
4)创建实例对象:
<1>通常方式:String str = new String(new StringBuffer("abc"));
<2>反射方式:String str = (String)constructor.newInstance(new StringBuffer("abc"));
5)Class.newInstance()方法:
<1>例子:String obj = (String)Class.forName("java.lang.String").newInstance();
<2>该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。
6)一个类有多个构造方法,用什么方式可以区分清楚想得到其中的哪个方法呢?根据参数的个数
和类型,例如:Class.getMethod(name,Class...args)中的args参数就代表所要获取的那个方法的
各个参数的类型的列表。重点:参数类型用什么方式表示?用Class实例对象。
四.成员变量的反射
1.Field类
1)Field类代表某个类中的一个成员变量。
2)注意:得到的Field对象是对应到类上面的成员变量,不是对应到对象上的成员变量,
字段fieldX代表的是x的定义,而不是具体的x变量。
3)代码演示:
- package cn.itcast.day1;
- public class ReflectPoint
- {
- private int x;
- public int y;
- public ReflectPoint(int x, int y) {
- super();
- this.x = x;
- this.y = y;
- }
- }
- package cn.itcast.day1;
- import java.lang.reflect.Constructor;
- import java.lang.reflect.Field;
- public class ReflectTest
- {
- public static void main(String[] args)throws Exception
- {
- ReflectPoint pt1 = new ReflectPoint(3,5);
- Field fieldY = pt1.getClass().getField("y");
- //fieldY的值是多少?不是5,fieldY不是对象身上的变量,而是类上,要用它去取某个对象上对应的值。
- System.out.println(fieldY.get(pt1));
- Field fieldX = pt1.getClass().getDeclaredField("x");//x 是私有变量,是看不见的,此方法则可看见,但不能用
- fieldX.setAccessible(true);//暴力反射:可强制使用已看到但不能用的私有变量。
- System.out.println(fieldX.get(pt1));
- }
- }
五.成员方法反射
1.Method类
1)Method类代表某个类中的一个成员方法
2)得到类中的某一个方法:
例子:Method charAt = Class.forName("java.lang.String").getMethod("charAt",int.class);
3)调用方法:
<1>通常方式:System.out.println(str.charAt(1));
<2>反射方式:System.out.println(charAt.invoke(str,1));
如果传递给Method对象的invoke()方法的一个参数为null,说明该Method对象对应的是一个静态方法。
2.对接收数组参数的成员方法进行反射
1)需求:
写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法
(用普通方式调完后,要明白为什么要用反射方式去调用?)
2)问题:
启动java程序的main方法的参数是一个字符串数组,即public static void main(String[] args),
通过反射方式来调用这个main方法时,如何为invoke方法传递参数呢?按jdk1.5的语法,
整个数组是一个参数,而按jdk1.4的语法,数组中的每个元素对应一个参数,因为jdk1.5
要兼容jdk1.4的语法,所以当把一个字符数组作为参数传递给invoke方法时,javac会按jdk1.4
的语法进行处理。不能使用代码:mainMethod.invoke(null,new String[]{"xxx"});
3)解决办法:
<1>mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});//即封装成一个参数
<2>mainMethod.invoke(null,(Object)new String[]{"xxx"});//这样做等于告诉编译器说这是一个参数
//编译器就不分把参数当数组看待,也不会把数组打散成若干个参数了.3.代码演示:
- import java.lang.reflect.Constructor;
- import java.lang.reflect.Field;
- import java.lang.reflect.Method;
- public class ReflectTest {
- public static void main(String[] args)throws Exception
- {
- //TestArguments.main(new String[]{"111","222","333"});
- String startingClassName = args[0];
- Method mainMethod = Class.forName(startingClassName).getMethod("main",String[].class);
- //mainMethod.invoke(null,new Object[]{new String[]{"111","222","333"}});
- mainMethod.invoke(null, (Object)new String[]{"111","222","333"});
- }
- }
- class TestArguments
- {
- public static void main(String[] args)
- {
- for(String arg : args)
- {
- System.out.println(arg);
- }
- }
- }
六.数组的反射与Object关系
1.数组反射
1)具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
2)代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class.
3)基本类型的一维数组可以被告当作Object类型使用,不能当作Object[]类型使用,
非基本类型的一维数组,即可以当作Object类型使用,也能当作Object[]类型使用。
2.代码演示:
int[] a1 = new int[]{1,2,3};
int[] a2 = new int[4];
int[][] a3 = new int[2][3];
String[] a4 = new String[]{"a","b","c"};
System.out.println(a1.getClass() == a2.getClass());
System.out.println(a1.getClass == a4.getClass());
System.out.println(a1.getClass() == a3.getClass());
System.out.println(a1.getClass().getName());
System.out.println(a1.getClass().getSuperclass().getName());//获取Class实例对象的父类对应的Class实例对象名称为Object
System.out.println(a4.getClass().getSuperclass().getName());
Object aobj1 = a1;
Object aobj2 = a4;
//Object[] aobj3 = a1;
Object[] aobj4 = a3;
Object[] aobj5 = a4;
System.out.println(a1);
System.out.println(a4);
System.out.println(Arrays.asList(a1));//--->a1整体相当于一个Object类型,故打印结果为一个对象的哈希值。
System.out.println(Arrays.asList(a4));//--->a4中相当于有三个Object类型,故打印结果为[a,b,c].3 Java.Lang.Reflect.Array类
1)public final class Array
extends Object
Array 类提供了动态创建和访问 Java 数组的方法。 Array 允许在执行 get 或 set 操作期间进行扩展转换,
但如果发生收缩转换,则抛出 IllegalArgumentException。
2)方法摘要
static Object get(Object array, int index)
返回指定数组对象中索引组件的值。
static int getLength(Object array)
以 int 形式返回指定数组对象的长度。
static void set(Object array, int index, Object value)
将指定数组对象中索引组件的值设置为指定的新值。
4.内存泄露;
当一个对象被存储到HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值
的字段了,否则,对象修改后哈希值就变了,这种情况下,使用contains方法传入该对象当前
引用作为参数无法检索到对象,这也导致无法从HashSet集合中单独删除当前对象,从而造成
内存泄露。
七.用反射技术开发框架的原理
1.反射的作用-->实现框架功能
1)框架与框架要解决的核心问题
<1>我做房子给用户住,用户自己安装门窗,我做的房子就是框架,用户需要使用我的框架,
把门窗插入进我提供的框架中,框架与工具类有区别,工具类被用户的类调用,而框架
则是调用用户提供的类。
<2>你做的门调用锁,锁是工具,你做的门被房子调用,房子是框架,房子和锁都是别人提供的。
2)框架要解决的核心问题:
<1>若干年前写的框架可以调用若干年后写的程序。
<2>写程序时无法知被调用的类名,所以在程序中无法直接new某个类的实例对象,
而要用反射来做。
八.用类加载器的方式管理资源和配置文件
1.类 ClassLoader
1)public abstract class ClassLoader extends Object类加载器是负责加载类的对象。
ClassLoader 类是一个抽象类。如果给定类的二进制名称,那么类加载器会试图查找或生成构成类定义的数据。
一般策略是将名称转换为某个文件名,然后从文件系统读取该名称的“类文件”。
每个 Class 对象都包含一个对定义它的 ClassLoader 的引用。
2)方法摘要
InputStream getResourceAsStream(String name)
返回读取指定资源的输入流。
2.将文件放到源文件下,会自动将它的字节码文件搬到classPath目录下。如:将config.properties放在包cn.itcast.day1下
未来学到的框架的配置文件都是放在classPath指定的目录下,因为它内部用的是类加载配置文件。3.代码分析:
1)InputStream ips = ReflectTest2.class.getClassLoader().getResourceAsStream("cn/itcast/day1/config.properties");
//此例运行是将配置文件放在了源文件(src)目录下,意为:从根目录下开始查找,若不加cn/itcast/day1的话就找不到文件。2)InputStream ips = ReflectTest2.class.getResourceAsStream("resources/config.properties");
//此例运行是将配置文件放在了源文件的新建包cn.itcast.day1.resources下,意为:从默认的程序路径下开始查找,即从包cn.itcast.day下找。
- 黑马程序员_高新技术2(Class类,反射Reflect(重点知识))
- 黑马程序员_高新技术二(Class类,反射Reflect(重点知识))
- 黑马程序员----Class类、反射(Reflect)
- 黑马程序员-高新技术-反射基石-Class类
- 黑马程序员—高新技术:Reflect反射
- 黑马程序员—高新技术_反射(2)
- 黑马程序员_高新技术------反射
- 黑马程序员_高新技术-反射
- 黑马程序员_高新技术_反射
- 黑马程序员_高新技术_反射
- 黑马程序员——Class类、反射(Reflect)
- 黑马程序员_Java高新技术二_反射
- 黑马程序员_Java高新技术_反射
- 黑马程序员_高新技术之反射
- 黑马程序员_高新技术之反射
- 黑马程序员_高新技术Java反射机制
- 黑马程序员_Java高新技术_反射
- 黑马程序员_高新技术:4) 注解、反射
- 关于new Handler().postDelayed()
- Max retries exceeded with ur
- iOS第六天
- myeclipse10安装JBPM5.4的插件
- 淘宝海量数据库OceanBase:系统架构详解
- 黑马程序员_高新技术2(Class类,反射Reflect(重点知识))
- svn删除文件恢复
- 斐波那契数列及变形题
- cocos2d-x类之间继承关系
- UVA10014 - Simple calculations
- chromium历史记录实现(不完整版)
- LA 2678 – Subsequence
- uva 11136 Hoax or what
- 远程连接webservice遇到无法访问的问题解决办法