黑马程序员———反射

来源:互联网 发布:霸气的句子 知乎 编辑:程序博客网 时间:2024/06/09 13:53
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

 

反射的基石--->Class


通过Class可以得到这个类身上方方面面的信息。
Java程序中的各个类属于同一类事物描述这类事物的Java
类名就是Class。

如Person类代表人它的各个实例对象就是张三,李四
这样一个个具体的人,Class类代表Java类,它的各个实例
对象又分别对应什么呢?
对应各个类在内存中的字节码,,例如:Person类的字节码,
ArrayList类的字节码,等等。
一个类被加载到内存中,占用一片存储空间,这个空间
里面的内容就是类的字节码,不同的类的字节码是不同的,
所以他们在内存中的内容是不同的,这一个个的空间可分别用一个个的对象来表示,
这些对象显然具有相同的类型,这个类型是什么呢?

Class不可以直接new

Person类   Data类   Math类
Class cls1=Data.class//字节码1;
Class cls2=Person.class//字节码2;

Class.forName("java.lang.String") 
返回字节码,返回的方式有两种,第一种就是这份字节码曾经被加载过,已经
呆在java虚拟机里面了,直接返回。还有一种是java虚拟机没有这份字节码,则
用类加载器去加载。把加载进来的字节码缓存进虚拟机,以后要得到这份
字节码就不用再加载了。


得到字节码有三种方式:
System.class

new Data().getClass();

Class.forName("java.util.Data");


九个预定义Class实例对象:
8个基本数据类型和void
参考Class.isPrimitive方法的帮助
Int.class==Integer.TYPE

数组类型的Class实例对象
Class.isArray();
总之,只要是在源程序中出现的类型,都有各自的Class实例对,例如
int[],void...


isPrimitive
public boolean isPrimitive()判定指定的 Class 对象是否表示一个基本类型。
有九种预定义的 Class 对象,表示八个基本类型和 void。这些类对象由 Java 虚拟机创建,与其表示的基本类型同名,即 boolean、byte、char、short、int、long、float 和 double。

这些对象仅能通过下列声明为 public static final 的变量访问,也是使此方法返回 true 的仅有的几个 Class 对象。


返回:
当且仅当该类表示一个基本类型时,才返回 true
从以下版本开始:
JDK1.1
另请参见:
Boolean.TYPE, Character.TYPE, Byte.TYPE, Short.TYPE, Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE, Void.TYPE

=====================================================================


反射就是把JAVA类中的各种成分映射成相应的JAVA类。
例如,一个JAVA类中用一个Class类的对象来表示,一个类
中的组成成分:成员变量,方法,构造方法,包等等信息
也用一个个的JAVA类来表示,就像汽车是一个类,汽车
中的发动机,变速箱等等也是一个个的类。表示java类的
Class类显然要提供一系列的方法,来获得其中的变量,方法
构造方法,修饰符,包等信息,这些信息就是用相应类的
实例对象来表示,它们是Field,Method,Contructor,
Package(默认)等等。

一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示
通过调研Class类的方法可以得到这些实例对象后,得到这些实例对象后有什么用呢?
怎么用呢?这正是学习和应用反射的要点。


=====================================================================

Constructor类代表某个类中的一个构造方法
得到某个类所有的构造方法:
例子:Constructor[] constructors=
  Class.forName("java.lang.String").getCostructor();
得到某一个构造方法:
例子:Constructor constructor=
  Class.forName("java.lang.String").getConstructor(StringBuffer.class);
  //获得方法时要用到类型。
创建实例对象:
通常方式:String str=new String(new String(new StringBuffer("abc"));
反射方式:String str=
  (String)constructor.newInstance(new StringBuffer("abc"));
 //通常获得的方法时要用到上面相同类型的实例对象。

Class.newInstance()方法:
例子:String obj=(String)Class.forName("java.lang.String").newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。
该方法内部的具体代码怎么写呢?用到了缓存机制来保存默认构造方法的对象。


如果用不带参数的构造方法,就直接用Class.newInstance();而不同构造器。
反射导致程序性能下降

Constructor -->newInstance()

 

=======================================================================

类身上的成员变量用Field表示。

Method类:
Method类代表某个类的一个成员方法
得到类中的某一个方法:
例子:Method charAt=
 Class.forName("java.lang.String").getMethod("charAt",int.class);
调用方法:
通常方式:sop(str.charAt(1));
反射方式:sop(charAt.invoke(str,1));
如果传递给Method对象的invoke方法的一个参数为null,说明该Method对象对应
的是一个静态方法。


jdk1.4和jdk1.5的invoke方法的区别:

jdk1.5:public Object invoke(Object obj,Object...args);
jdk1.4: public Object invoke(Object obj,Object[] args);
即按照jdk1.4的语法,需要将一个数组作为参数传递给invoke方法时,
数组的每一个元素分别对应被调用方法中的一个参数,所以,调用charAt方法的代码
也可以用jdk1.5改写为charAt.invoke("str",new Object[]{1})形式。


=============================================================

 

用反射的方式执行某个类中的main方法。
目标:根据用户提供的类名去执行该类中main方法。

mainMethod.invoke(null, new Object[]{new String[]{"111","222","333"}});
mainMethod.invoke(null, (Object)new String[]{"111","222","333"});

 

====================================

 

数组的反射:
具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
代表数组的Class实例对象的getSuperclass()方法返回的父类Object类对应的Class
基本类型的一维数组可以被当做Object类型使用,不能当做Object[]类型使用,非基本类型的一维数组,
既可以当做Object类型使用,又可以当做Object[]类型使用。
//Arrays.asList()处理int[]和String[]的差异。
Array工具类用于完成对数组的发射操作。
怎么得到数组中的元素类型?


==============================================

 


反射的作用--》实现框架作用。

配置文件的位置:
得到具体的路径:getRealPath();//金山词霸/内部位置

得到那个总的目录,在硬盘上的绝对位置,不管软件安装在
哪里,都能找到绝对路径。


哈希码有什么作用呢?
哈希算法把集合分成若干个存储区域,每个对象可以计算出一个哈希码,可以将哈希码分组,每组分别
对应某个存储区域,根据一个对象的哈希码就可以确定该对象应该在哪个区域。
 
      哈希值对应区  哈希值对应区  哈希值对应区
| 域1的对象  | 域2的对象 | 域3的对象 |
---------------------------------------------------------
| | | | | | | | | | | | | |
--------------------------------------------------------
| 区域1  | 区域2  |  区域3 | 区域n

*
*HashSet就是采用哈希算法存储对象的集合,它内部对某个数字n进行取余的方式对哈希码
*进行分组和划分对象的存储区域。当HashSet集合查找某个对象时,首先调用
*hashCode()方法获得该对象的哈希码。
*
*能防止内存泄露。
*
*java有内存泄露吗?为什么?
*有。假设有个对象我不用了,但它占用内存空间,没有被释放,这就叫内存泄露。
*举例说明呢?上面y值的改变就是例子。
*/
======================================

框架就是用类加载器的方式来加载配置文件
配置文件必须放在classPath指定的目录下。

 


===========================================

内省:
IntroSpector--->JavaBean-->特殊的Java类

符合特殊规则的Java类。
int getAge();
void setAge(int age);

像这种特殊的set get方法,可以用JavaBean方式也可以不用
JavaBean方式来操作。


JavaBean根据的方法的名称推出返回的是什么,
把Person当做JavaBean操作,它有一个age属性。

class Person
{
 private int x;
 public int getAge()
 {
  return x;
 }
 public void setAge(int age)
 {
  this.x=age;
 }
}

 

JavaBean主要用于传递信息,这种java类中的方法主要
用于访问私有的字段,且方法名符合某种命名规则。
如果要在两块模块之间传递多个信息,可以将这些信息
封装到一个JavaBean中,这种JavaBean的实例对象通常
称之为值对象(Value Object)VO。这些信息在类中用私有
字段来存储。JavaBean的属性根据setter和getter
方法来确定。

去掉set或get前缀,。
Age--->如果第二个字母是小的,则把第一个字母变成小的-->age

gettime-->time
getTime-->time
getCPU-->CPU

后者代表属性。
一个类被当做Javabean使用,JavaBean的属性根据方法
名推断出来,他根本看不到java类内部成员变量。

有相应的API操作方式,JAVAEE开发,JavaBean相对频繁。

IntroSpector.getBeanInfo();

 


操作javaBean的包:common beanUtils 
common logging 


=========================================
JDK1.5的新特性之一:


了解注解和java提供的几个基本注释。


@SuppressWarnings

@Deprecated

@Override


注解的应用结构图


注解类 应用了“注解类”的类    对应用了“注解类”
    的类进行反射操作的类
        
@interface A @A  Class C{
{  Class B  B.class.isAnnotionPresent(
{  {   A.class);
  }  A a = B.class.getAnnotion(
     A.class);
    }
     

 

为注解增加高级属性

数组类型的属性:
int[] arratAttr() default{1,2,3};
@MyAnnotation(ArrayAttr={2,3,4})
如果数组属性中只有一个元素,这时候属性值部分可以
省略大括号。
枚举类型的属性:
EnumTest.TrafficLamp lamp();
@MyAnnotation(lamp=EnumTest.TrafficLamp.GREEN)
注解类型的属性:
MetaAnnotation annotationAttr() default@MeteAnnotation("xxxx");
@MyAnnotation(anotationAttr=@MetaAnnptation("yy"))
可以认为上面这个@MyAnnotation是MyAnnotation类的
一个实例对象,同样的道理,可以认为上面这个@MetaAnnotation
是MetaAnnotation类的一个实例对象,调用代码如下;
MetaAnnotation ma = myAnnotation.annotationAttr();
System.out.println(ma.value);

 

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------


 

0 0
原创粉丝点击