----------------------- android培训、java培训、java学习型技术博客、期待与您交流! ----------------------
Java基础加强(二)
(一) 枚举
1, 枚举就是让某个类型的变量的取值只能为若干个固定值中的一个。否则,编译器就会报错,枚举可以让编译器在编译时就可以控制源程序中填写的非法值,普通变量的方式在开发阶段无法实现的。
2, 模拟枚举实现的原理:
如:定义一个普通的类去实现枚举
思路:
(1)私有构造函数(枚举取的是固定的值,所以不能让外界创建对象进行实例化)
(2)每一个元素分别用一个公有的静态成员变量表示(静态成员变量是被所有的对象共享的数据,但是,外界不能创建对象,那么该静态成员变量的值就不能被修改,所以最好在静态成员变量前加入final关键字修饰)
(3)可以有若干公有方法或抽象方法,例如:要提供nextDay方法必须是抽象的(采用抽象方法定义nextDay就将大量的if else语句转移成一个个独立的类。如果想在一个类中编写完各个枚举类和测试调用类,那么可以将枚举列定义成调用类的内部类。)
privateWeekDay1(){}//不让别人创建对象
publicfinal static WeekDay1 SUN=new WeekDay1(){//内部类
publicWeekDay1 nextDay(){
returnMON;
}
};
publicfinal static WeekDay1 MON=new WeekDay1(){
public WeekDay1 nextDay(){
returnSUN;
}
};
public abstract WeekDay1 nextDay();
3, 枚举与单例设计模式
(1) 单例设计模式:保证一个类在内存对象中的唯一性(两种表现形式:饿汉式和懒汉式:双重if判断,是为了提高效率;使用同步是为了安全)
(2) 枚举:它就是让某个类型的变量的取值为它自己设定的固定值。那么,当枚举中,有且仅有一个对象的时候,此时我们可以将它看成是单例设计模式
友情提示:如果枚举中有多个变量时,那么此时我们不建议使用if else进行多重判断,而是直接是内部类解决该问题,将大量的if else语句转移成一个个独立的类。
4, 构造方法
(1) 构造方法必须放在变量后面
(2) 设置多个变量结束后,需要在该变量的后面加上分号
(3) 构造方法必须被私有
(4) 当构造方法带参数时,需要让变量访问指定的构造函数,此时,我们可以变量后面加上括号并传入指定的类型(构造函数中的参数类型)
5, 实现带有抽象的枚举
RED(30){//子类需要完成父类的抽象方法(首先是三个元素,然后是大括号,表示的是子类,由子类实现父类中的抽象方法)
publicTrafficLamp nextLamp(){//这个类中有一个方法,该方法的返回值类型还是该类型
returnGREEN;//红灯以后是绿灯
}
},;
publicabstract TrafficLamp nextLamp();
privateint time;
privateTrafficLamp(int time){
this.time=time;
}
(二)反射
1,简单的说:就是能动态的获取一个类中的信息,就称之为Java的反射(反射就是把Java类中的各种成分映射成相应的java类)。,其实,反射机制就是对字节码文件进行解剖,也就是获取字节码文件中的相关信息,如何才能获取到呢?这时,我们可以通过Class类中的forName方法完成。
String className = "cn.itcast.bean.Person";
Classclazz = Class.forName(className);
System.out.println(clazz);
这种方式只要有名称即可,更为方便,扩展性更强。反射的时候以这种方式为主。
友情提示:Class.forName(“java.lang.String”)的作用
作用:返回字节码,返回的方式有两种:
第一种:该字节码曾经被加载过,已经存在了,直接找到该字节码并返回就可以了
第二种:Java虚拟机中还没有改字节码,则用类加载器去加载,把加载进来的字节码缓存在虚拟机里面,以后要想得到该字节码就不需要加载了
2,Class类代表Java类(Class描述的是java的类名),它的各个实例对象对应各个类在内存中的字节码(所谓的Class就是描述Java事物的类名)
3,得到各个字节码对应的实例对象( Class类型)
(1) 类名.class,例如,System.class
(2) 对象.getClass(),例如,new Date().getClass()
(3) Class.forName("类名"),例如,Class.forName("java.util.Date");
4, 数组类型的Class实例对象:Class.isArray()
5, 总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如,int[],void…
Class clazz=void.class;
System.out.println(clazz);//void
System.out.println(int[].class.isArray());//true
6,反射类的成员方法:
Class clazz = Person.class;
Method method = clazz.getMethod(methodName,new Class[]{paramClazz1, paramClazz2});
method.invoke();
7,反射类的构造函数:
Constructor con = clazz.getConstructor(newClass[]{paramClazz1, paramClazz2,...})
con.newInstance(params...)
友情提示:需要注意的是:构造函数的类型以及传入参数的的对象类型需要保持一致。
8,反射类的属性:
Field field = clazz.getField(fieldName);
field.setAccessible(true);
field.setObject(value);
9,Field类:Field类代表某个类中的一个成员变量
对于一个类中的私有成员,我们可以使用getDeclaredField方法去获取它的私有成员,但是,此时能知道该类中有私有成员,但是不能取出来,所以,我们可以使用暴力反射强制获取内容:setAccessible(true)。
10,Method类:代表某个类中的一个成员方法
调用方法:
通常方式:System.out.println(str.charAt(1));
反射方式: System.out.println(charAt.invoke(str, 1));
友情提示:
(1)成员方法,那么它就有参数类型,那么参数类型用什么来表示呢?用Class对象
(2)如果传递给Method对象的invoke()方法的第一个参数为null,这有着什么样的意义呢?说明该Method对象对应的是一个静态方法!
11,数组的反射
特点:
(1)具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象(此处比较与值无关)。
(2)代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class。
(3)基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用
友情提示:
(1)基本数据类型不是Object
(2)Arrays.asList()方法处理int[]和String[]时的差异?
Arrays.asList()方法使用的是:public static <T> List<T> asList(T... a)
如果是整型,就把它当作是一个参数直接传入进去;对于字符串来说,成功的转换成了一个个list对象,属于Object类型
----------------------- android培训、java培训、java学习型技术博客、期待与您交流! ----------------------