黑马程序员--Java基础加强(二)

时间:2021-10-03 12:14:55

----------------------- 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虚拟机中还没有改字节码,则用类加载器去加载,把加载进来的字节码缓存在虚拟机里面,以后要想得到该字节码就不需要加载了

 

2Class类代表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);

9Field类:Field类代表某个类中的一个成员变量

对于一个类中的私有成员,我们可以使用getDeclaredField方法去获取它的私有成员,但是,此时能知道该类中有私有成员,但是不能取出来,所以,我们可以使用暴力反射强制获取内容:setAccessible(true)

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

调用方法:

通常方式: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

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

Arrays.asList()方法使用的是:public static <T> List<T> asList(T... a)

如果是整型,就把它当作是一个参数直接传入进去;对于字符串来说,成功的转换成了一个个list对象,属于Object类型

 

----------------------- android培训java培训java学习型技术博客、期待与您交流! ----------------------