枚举

来源:互联网 发布:路由器可以限制端口吗 编辑:程序博客网 时间:2024/05/16 09:28

享元模式Flyweight Pattern

枚举 反射 - 九五二七 - 今天

 

枚举 反射 - 九五二七 - 今天

 枚举enumeratin

 为什么要有枚举

问题:要定义星期几或性别的变量,该怎么定义?

假设用1-7分别表示星期一到星期日,但有人可能会写成int weekday = 0;

枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则编译器就会报错.

枚举可在编译时就发现源程序中填写的非法值,普通变量无法实现.

[生活中的例子,开发程序时用几表示Sunday呢,有的用1(在国外是一周的第一天),用0(计算机中第一用0表示)或者用7(在中国是第七天)。都有道理,那么公司规定我的公司Sunday就用0表示,Saturday6表示。但是这样的小细节要对每个新来的程序员都告诉一遍吗?麻烦!要定义一个Weekday,里面设定好值,以后程序员要用Weekday型变量时,它的值只能是应经提前定义好的值.这个值不是基本类型的,而是引用类型的,是对象]

枚举 反射 - 九五二七 - 今天

 

枚举 反射 - 九五二七 - 今天

 

定义一个Weekday的类来模拟普通类实现枚举功能。 。

定义抽象方法nextDay,将大量的if.else语句转移成了一个个独立的内部类。


枚举就相当于一个类,可定义成员变量,构造方法,普通方法和抽象方法。

枚举 反射 - 九五二七 - 今天

 

枚举元素必须位于枚举体中的最开始部分。

枚举 反射 - 九五二七 - 今天

 

枚举 反射 - 九五二七 - 今天

 

总结:枚举是一种特殊的类,其中的每个元素都是该类的一个实例对象

例如可以调用WeekDay.SUN.getClass().getNameWeekDay.class.getName()

 

反射的基石àClass类

Java程序中的各个Java类属于同一事物,Class

众多的人用Person类表示

众多的Java类用Class类表示

Person类有人的姓名年龄等属性,学习吃饭等方法

Class类

 

Person p1 = new Persion();   //先把java文件,编译成二进制的字节码,即class文件

Person p2 = new Persion();   //当程序用到Person类时,先把Person的字节码加载到内存后,创建对象 即:先把字节码加载到内存,通过字节码创建类的对象

 

如果用了Person类,Date类,Math类,内存中就有3分字节码文件,即3Class类的实例对象

Class c1 = Date.class   //Class类不能new对象,但可以指向。内存中若有Date类,就有Date对应的字节码,这个字节码就是对象,这个对象的类型就是Class

p1 就是Person类字节码创建出的一个对象

p1.getClass();   p1有相应的方法得到是哪个字节码创建的自己

 

得到字节码的三种方式:

1.字节码已经加载到内存 直接类名.class,例如,System.class

2.字节码已经加载到内存 对象.getClass(),例如,new Date().getClass()

3.字节码没加载到JVM  Class类的静态方法forName

Class.forName("类名"),例如,Class.forName("java.util.Date");

若没加载就先用类加载器把指定的类加载到内存,同时forName方法返回加载的字节码

 

Class<T> API:

The primitive Java types (boolean, byte, char, short, int, long, float, and double), and the keyword void are also represented as Class objects.

基本的 Java 类型(booleanbytecharshortintlongfloat  double)和关键字 void 也表示为Class 对象。

枚举 反射 - 九五二七 - 今天

 

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

 

反射:

 

学员冯伟立(大二辍学,现广州电信)听完后反射后的一句总结:反射就是把Java类中的各种成分映射成相应的java。这句话比许多书上讲解得都透彻,都精辟!

 

就像汽车是一个类,汽车中的发动机,变速箱,轮胎等也是一个个的类。

表示java类的Class类要提供一系列的方法,来获得其中的变量,方法,构造方法等信息。这些信息就是用相应类的实例对象来表示,它们是FieldContructorPackage等等。

 

一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示

通过调用Class类的方法可得到这些实例对象

得到这些实例对象后有什么用呢?怎么用呢?这正是学习和应用反射的要点

 

Constructor类

枚举 反射 - 九五二七 - 今天

 

Field类

暴力反射

枚举 反射 - 九五二七 - 今天

 

成员变量的反射与成员方法的反射

作业:将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的"n"改成"*"

枚举 反射 - 九五二七 - 今天

 

 

s1.charAt,  s2.charAt                    

s1与s2都能调用同一方法,方法是属于类的,不是属于对象的

 

invoke

[?n'vok] vt. 调用;招灵

方法调用

method invocation

Method类代表某个类中的一个成员方法

得到类中的某一个方法:

例子:         Method m = Class.forName("java.lang.String").getMethod("charAt", int.class);

获得String类的Method类中charAt方法,该charAt方法有多种重载方式,这里我们选参数时int型的,就要写出int.class

这要就得到了Method类中的对象mm具体是String类中的charAt方法,且参数是int型。如何使用对象m中的方法,方法需要被对象调用,故m.invoke(str,1)把对象和参数通过Method类中的invoke方法传给m

Invoke要理解:关门,不是人关门,人给一个力量,一个信号,门自己关的自己知道回到哪儿位置,

Circle。Draw.是你发命令,circle自己画圆

(面向对象:把变量私有,谁操作变量,变量在谁身上,方法就在谁身上,关门 门与门槛角度为0,这个角度是门的,角度变小的方法在门身上)

 

调用方法:

通常方式:System.out.println(str.charAt(1));

反射方式: System.out.println(charAt.invoke(str, 1));

如果传递给Method对象的invoke()方法的第一个参数为null,这有着什么样的意义呢?说明该Method对象对应的是一个静态方法!

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

Jdk1.5:public Object invoke(Object obj,Object... args)

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

 

Class.getMethod方法用于得到一个方法,该方法要接受什么参数呢?显然要一个方法名,而一个同名的方法有多个重载形式,用什么方式可以区分清楚想得到重载方法系列中的哪个方法呢?根据参数的个数和类型,例如,Class.getMethod(name,Class... args)中的args参数就代表所要获取的那个方法的各个参数的类型的列表。

再强调一遍参数类型用什么来表示啊?用Class对象!

稍后总结(就像看书如果卡在第五页了,就跳过去看第10页,不要反复看前五页)

枚举 反射 - 九五二七 - 今天

 

m.invoke(null,1);

当传入的对象为null,是就是该方法不需要对象调用,即静态方法

用反射方式执行某个类中的main方法

枚举 反射 - 九五二七 - 今天

 

大家要明白为什么要用反射方式去调啊?

问题:按jdk1.5的语法,整个数组是一个参数,而按jdk1.4的语法,数组中的每个元素对应一个参数

jdk1.5肯定要兼容jdk1.4的语法,会按jdk1.4的语法进行处理,即把数组打散成为若干个单独的参数。所以,在给main方法传递参数时,不能使用代码mainMethod.invoke(null,new String[]{xxx})javac只把它当作jdk1.4的语法进行理解,而不把它当作jdk1.5的语法解释,因此会出现参数类型不对的问题。

解决办法:mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});

mainMethod.invoke(null,(Object)new String[]{"xxx"}); ,编译器会作特殊处理,编译时不把参数当作数组看待,也就不会数组打散成若干个参数了

枚举 反射 - 九五二七 - 今天

 

数组的反射

枚举 反射 - 九五二七 - 今天

Arrays.asList()方法处理int[]String[]时的差异。

Array工具类用于完成对数组的反射操作。

枚举 反射 - 九五二七 - 今天

 Object[] 与String[]没有父子关系,ObjectString有父子关系

:new Object[]{“aaa”,”bb”}不能强制转换成new String[]{“aaa”,”bb”};

Object x = “abc”能强制转换成String x = “abc”

main.invoke(null, (Object)(new Object[]{“aaa”,“xxx”}));

不能调用public static void main(String [] args)

  

反射到底干什么:实现框架

框架与工具类的区别:

我作为开发商建房子卖给住户,由住户自己安装门窗,我建的房子就是框架

住户需使用我的框架,把门窗插入进我提供的框架中.

住户自己做的门,然后到商店买一个锁安装上,锁就是工具类

工具类被用户的类调用,而框架则是调用用户提供的类。

枚举 反射 - 九五二七 - 今天

 框架要解决的核心问题

我在写框架(房子)时,调用你未来的那个门,就是我建房子时,你还没做门

这时不能直接new某个门,因为门还没有,怎样能调用到后写的类(门窗)呢?

要用反射方式来做,通过Class向回找

 综合案例

先直接用new语句创建ArrayListHashSet的实例对象

通过eclipse可自动生成 ReflectPoint类的equalshashcode方法

枚举 反射 - 九五二七 - 今天

 

枚举 反射 - 九五二七 - 今天

 

 

Class类也提供getResourceAsStream方法

好比:你每次都找我给你商店买可乐,那我还不如直接向你买可乐,即直接提供一个买可乐的方法给你

0 0
原创粉丝点击