黑马程序员_java基础加强-枚举和反射
来源:互联网 发布:淘宝金牌卖家 编辑:程序博客网 时间:2024/06/10 09:50
---------- android培训、java培训、期待与您交流! ----------
1.枚举:
目的:让某个类型的变量取值只能为若干个固定值中的一个,否则,编译器会报错;
作用:可以让编译器在编译时就可以控制源程序中填写的非法值,普通变量的方式在开发阶段无法实现这一目标。
练习:用普通类如何实现枚举功能,定义一个Weekday的类来模拟枚举功能。
步骤: 1.私有构造函数,防止外部随意创建对象;
2.每个元素分别用一个公有的静态成员变量表示;
3.可以有若干公有方法或抽象方法,例如,要提供nextDay()方法必须是抽象的,因为具体的星期中的第一天是星期几我们是不知道的。
class WeekDayDemo{public static void main(String[] args) {WeekDay weekDay=WeekDay.MON;System.out.println(weekDay.nextDay());}}//将nextDay方法分别由其子类去覆写它中的内容abstract class WeekDay{
//在这里假设一周只有两天,周一和周日,循环。public final static WeekDay SUN=new WeekDay(){@Overridepublic WeekDay nextDay() {return MON;}};public final static WeekDay MON=new WeekDay(){@Overridepublic WeekDay nextDay() {return SUN;}};private WeekDay(){}public String toString(){return this==SUN?"SUN":"MON";}public abstract WeekDay nextDay();/*public WeekDay nextDay(){if(this==SUN){return MON;}else{return SUN;}}*///将许多的if else语句转成了一个个独立的类,有多少个子类,就转成多少个类。}
枚举的基本应用:定义一个WeekDay枚举,包括一些基本方法;class WeekDay{public static void main(String[] args) {WeekDay weekDay1=WeekDay.FRI;System.out.println(weekDay1);//这里已经覆写过toString方法,可以直接输出对象内容;System.out.println(weekDay1.name());System.out.println(weekDay1.ordinal());//获取到枚举的序数System.out.println(WeekDay.valueOf("SUN".toString()));//将参数列表中的参数变为对象System.out.println(WeekDay.values().length);//values方法将其变为数组}
//在类中定义一个枚举public enum WeekDay{SUN,MON,TUE,WED,THD,FRI,SAR;}}
总结:枚举是一种特殊的类,其中的每个元素都是该类的一个实例对象,
实现带构造函数的枚举:
注意:枚举类Enum中的构造函数 protected Enum(String name,int ordinal),程序员无法调用此构造方法,只有它的子类才能使用,用于由响应枚 举类型声明的编译器发出的代码。
在上面代码基础之上:
public enum WeekDay{SUN(1),MON,TUE,WED,THD,FRI,SAR;private WeekDay(){System.out.println("first");}private WeekDay(int day){System.out.println("second");}
//在这里,有两个构造函数,如果想知道对象在静态初始化后,调用的是哪个构造函数,可以通过看对象是否带有参数。
// 如这里的SUN就调用的有参构造函数。
}}
实现带有抽象方法的枚举:
class EnumTrafficLamp{public static void main(String[] args){TrafficLamp tl=TrafficLamp.GREEN;System.out.println(tl.nextLamp());}public enum TrafficLamp {
//因TrafficLamp是抽象的,所以创建它的三个子类RED,GREEN,YELLOW来覆写它的抽象方法
//RED(20l) {@Overridepublic TrafficLamp nextLamp() {return GREEN;}},GREEN(32l) {@Overridepublic TrafficLamp nextLamp() {return YELLOW;}},YELLOW(10l){@Overridepublic TrafficLamp nextLamp() {return RED;}};public abstract TrafficLamp nextLamp();
//定义时间,作为交通灯的等待时间private long time;TrafficLamp(long time){this.time=time;}}}
注意:枚举中只有一个成员变量时,可以作为一种单例的实现方式。
2.反射(JDK1.2就有的特性)
1.反射的基石:Class,它是一个类,java中各个类都是类,描述这些类的类就是Class.即Class是描述java中类的类;
基本方法应用:它没有公有的构造函数,不能通过new来创建实例对象,而是根据加载进内存的.class文件,如:
Person p1=new Person();Person p2=new Person();Class c1=Person.class;//Person类的的字节码就是Class类的一个实例。
p1.getClass();//获得对象所属的类的字节码
Class.forName("java.lang.String");
//得到类的字节码,返回方式两种:如果已加载进内存,则不需再加载直接返回;如果虚拟机中没有此字节码,类加载区需加载,缓存在JVM中,以后不用再加载;
总结:得到各个类实例对象的三种方式:1.类名.class;如System.class
2.对象.getClass();如new Person().getClass();
3.Class.forName("类名");如Class.forName("java.lang.Date");
九个预定义的Class对象:八个基本数据类型加 void;
Class中有一个方法isPrimitive(),返回布尔型,判断指定的Class实例对象是否表示一个基本数据类型。
Class cl=void.class;//表示void的Class实例对象
String s="abc";Class c1=s.getClass();Class c2=String.class;Class c3=Class.forName("java.lang.String");//这里会抛异常,因为可能类名写错以致找不到类。
System.out.println(c1==c2);//true
System.out.println(c1==c3);//true
System.out.println(c1.isPrimitive());//false,因为String类不是基本类型。
System.out.println(int.class==Integer.TYPE);//true
System.out.println(int[].class.isArray());//数组的Class实例对象,true
总结:只要是在源程序中的类型,都有自己的Class实例对象。2.反射:把java类中的各种成分映射成相应的java类。
动态的获取类中的内容,自动去找相应的类,并自动加载这个类创建该类的实例对象;在类中,将类中的Filed,Method, Constructor,Package都封装成各自的类。
好处:提高了程序的扩展性(多态也能提高程序的扩展性,但要自己new对象,而反射自动new对象,不用手动操作)。
class Class{//Class类中的属性Field field;//字段Constructor constructor;//构造器Method method;//方法//Class类中的方法Field getField(name);//获取单个字段Field[] getFields;//获取所有所有字段Constructor getConstructor();//获取单个构造函数Constructor[] getConstructors();//获取所有构造函数Method getMethod();//获取方法Method[] getMethods();}
反射首先要获取到字节码文件Class的对象,有三种方式:方式一:通过对象的getClass()方法;如Class cla=对象.getClass();该种方式不利于扩展,因其需要使用该类对象,并还需创建该类对象;
方式二:任何一个数据类型,都对应着一个类的描述,都可以获取到对应的Class对象,而且通过数据类型的一个静态属性.class完成,但还是要用到对象,对扩展性仍然不好;
方式三:通过Class类中的静态方法forName(String name)方法,根据指定的字符串名称(全类名),可以获取到对应的字节码文件;这种方式不会用到对象,扩展性最好;
如 Class cla=Class.forName("java.lang.String");
反射第二步是创建字节码文件的对象,即Class具体描述的食物实例;
Class cla=Class.forName("java.lang.Object);Object obj=cla.newInstance();
//这两句话相当于下面一句话;
Object obj=new Object();
Object obj=new Object();这句话的原理:
1.加载了java.lang.Object.class文件进内存;
2.将该文件封装成Class对象;
3.通过new关键字在堆内存中分配空间;
4.调用空参数的构造函数堆该类对象进行初始化。
Class cla=Class.forName("java.lang.Object:);
Object obj=cla.newInstance();原理:
1.查找指定的字节码文件;
2.将其加载进内存,并封装成Class对象;
3.通过newInstance创建实例;其实就是在该方法内部通过new关键字创建实例,并调用空参的构造方法对对象进行初始化。
注意:newInstance只能调用空参数的构造函数初始化对象。
反射第三步,创建字节码文件的带参数的对象,首先获取到这个构造函数的对象;代码体现如下:
Class cla=Class.forName("java.lang.String");Object obj=cla.newInstance();
//获取字节码文件对象对应的构造函数Constructor con=cla.getConstructor(String.class);
//通过指定的构造函数new实例对象String s=(String)con.newInstance("acd");System.out.println(s);
反射四:通过反射调用对象中的属性,Field类;
Class cla=Class.forName("cn.itcast.Person");Object obj=cla.newInstance();//age属性被私有Field field=cla.getDeclaredField("age");
//需设置为可访问field.setAccessible(true);
//对对象的age属性赋值field.set(obj, 22);field.get(obj);//toString方法被复写System.out.println(obj);
反射五:动态获取指定类中的方法;getMethods():获取所有方法,包括从父类继承来的方法;
getDeclaredMethods():获取本类中所有权限的方法,不包括从父类继承来的方法。
获取public修饰的方法:
Class cla=Class.forName("cn.itcast.Person");
Object obj=cla.newInstance();Method method=cla.getMethod("方法名",null);//后面的这个参数是方法中的参数列表method.invoke(obj, null);
获取private修饰的方法:Class cla=Class.forName("cn.itcast.Person");Object obj=cla.newInstance();Method method=cla.getDeclaredMethod("方法名",null);method.setAccessible(true);method.invoke(obj, null);
获取static修饰的方法:Class cla=Class.forName("cn.itcast.Person");Object obj=cla.newInstance();Method method=cla.getMethod("方法名",null);method.invoke(null, null);//静态方法不需要对象
获取有参数的方法:Class cla=Class.forName("cn.itcast.Person");Object obj=cla.newInstance();Method method=cla.getMethod("Study",String.class,int.class);method.invoke(obj, "lisi",23);
练习:将任意一个对象中的String类型的成员变量所对应的字符串内容中的"b"改为"a"。public class Test {public static void main(String[] args) throws Exception {//获取字节码文件Class cla=Class.forName("Test.Ball");//创建字节码文件对象Object obj=cla.newInstance();//获取所有字段Field[] fields=obj.getClass().getDeclaredFields();for (Field field : fields) {field.setAccessible(true);//遍历所有符合条件的字段类型if (field.getType()==String.class) {String oldValue=(String)field.get(obj);String newValue=oldValue.replace('b','a');field.set(obj, newValue);}}System.out.println(obj);}}class Ball{private String s1="ball";private String s2="basketball";private String s3="pingpeng";public String toString(){return s1+"::"+s2+"::"+s3;}}
---------- android培训、java培训、期待与您交流! ----------
- 黑马程序员_java基础加强-枚举和反射
- 黑马程序员_java基础加强之枚举
- 黑马程序员_Java基础加强_枚举
- 黑马程序员_Java基础加强之反射
- 黑马程序员_java基础加强之反射
- 黑马程序员_Java基础加强_反射
- 黑马程序员_Java基础加强反射
- 黑马程序员_Java基础加强_反射
- 黑马程序员_张孝祥_Java基础加强_枚举类
- 黑马程序员_java基础加强学习之枚举
- 黑马程序员_java基础加强之(反射)
- 黑马程序员_张孝祥_Java基础加强_反射
- 黑马程序员_JAVA基础加强——反射
- 黑马程序员_java基础加强
- 黑马程序员_JAVA基础加强
- 黑马程序员_Java基础加强
- 黑马程序员_Java基础加强
- 黑马程序员_java基础加强
- Websphere Application Server 6.1安装配置
- 5,两个不交叉的有序链表的合并
- IDA使用初探-1.启动IDA
- 论---价值投资背后的数学原理
- Crypto Obfuscator For .Net Version 2012 R2 Build 120922
- 黑马程序员_java基础加强-枚举和反射
- eclipse怎么部署项目到tomcat
- 文件描述符和文件系统和设备文件
- iframe跨域javascript访问
- ACM-杭电 HDOJ-1216 模拟,链表
- CXF初步教程
- 模拟音频接口详解
- java类的构造器
- 【VC编程技巧】动态链接库☞1.4进程间共享数据