黑马程序员__高新技术2

来源:互联网 发布:乐秀rx5数据 编辑:程序博客网 时间:2024/06/10 03:52

 ------- android培训、java培训、期待与您交流! ----------

1、枚举

a)        public abstract class Enum<E extends Enum<E>>extends Object implements Comparable<E>, Serializable

                         i.             这个类是所有 Java语言枚举类型公共基本类

b)        用一个普通类来模拟枚举类:

                         i.             这个类必须是 abstract型的;

                       ii.             这个类必须是 static型的;

1.        因为一个枚举可变被定义到另个一个普通类的内部,并且枚举中的成员变量都是static型的本枚举类对象。

                      iii.             这个类的构造函数必须是private型的;

                     iv.             这个类中的成员变量(也即是枚举元素的变量)必须是 public型的、final型的、static型的本类类型对象;

                       v.             这个类中的其他成员变量(也即非枚举元素的变量)必须是private型的;

                     vi.             这个类中的其他相关成员函数必须是publici型的、abstract型的;

                    vii.             这个类中的其他成员函数不做要求。

                  viii.             最好实现java.lang.Comparable接口。因为Enum默认实现了java.lang.Comparable接口。

                     ix.             用一个普通类来模拟枚举类的示例:

       abstract static class WeekDay1 {

              private WeekDay1(){}

             

              public final static WeekDay1 SUN = new WeekDay1(){

 

                     @Override

                     public WeekDay1 nextDay() {

                            // TODO Auto-generated method stub

                            return MON;

                     }

                    

              };

              public final static WeekDay1 MON = new WeekDay1(){

 

                     @Override

                     public WeekDay1 nextDay() {

                            // TODO Auto-generated method stub

                            return SUN;

                     }

                    

              };   

      

              public abstract WeekDay1 nextDay();//必须得有这么一句。否则,WeekDay1型的对象无法访问到nextDay()方法。

      

              public String toString(){

                     return this==SUN?"SUN":"MON";

              }

       }

c)        可以在一个main函数中这样来使用枚举:(这个枚举类定义在一个外部类的内部)

              外部类名.WeekDay1 sun=外部类名.WeekDay1.SUN;

              sop(sun.nextDay());

d)        枚举只有一个成员时,就可以作为一种单例的实现方式。

                         i.             也即还可以使用只有一个成员的枚举来实现一个单例设计模式

关于强制类型转换:

1、强制类型转换的条件

a)        必须在一对子父类之间;

b)        必须存在多态;

                         i.             也即只有  父类名称父类变量名称=子类对象实例 ;时才可以把这个父类变量名称强制转换成子类对象的引用;

1.       也即只有父类名称父类变量名称 =子类对象实例 ;才能   子类名称 子类变量名称 = (子类名称)父类变量名称 ;

c)        因此 Object[]  objArr  =  new Object[]{“aaa”,”bb”} ;

        不能这样转换: String[] strArr  =  (String[]) objArr  ;

d)         如果 Object[]  objArr  =  new String[]{“aaa”,”bb”} ;那么才可以转换成        String[] strArr  =  (String[]) objArr  ;

e)        这些都是经过验证的!!

2、关于框架和工具类:在开发程序过程中

a)        我调用别人的类,这个被调用的类就工具类

b)        别人的类调用我的类,这个别人的类就是框架

3、由一个小问题引发的:

a)         编译失败代码

int [] a1 = new int[]{1,2,3};

String [] a4 = new String[]{"a","b","c"};

System.out.println(a1.getClass() == a4.getClass());//编译失败为什么?  

b)        出错提示

---------- javac ----------

HelloWorld.java:33: 不可比较的类型java.lang.Class<capture#734 of ? extends int[]> java.lang.Class<capture#774 of ? extends java.lang.String[]>

        System.out.println((a1.getClass()) = = (a4.getClass()));

                                    ^      

1 错误

输出完成 (耗时 0) - 正常终止

c)        而写成

int [] a1 = new int[]{1,2,3};

String [] a4 = new String[]{"a","b","c"}; 

 

Class clazz1=a1.getClass();

Class clazz3=a4.getClass();

System.out.println(clazz1 ==clazz3);

就不会出错了。

d)        解决问题

int [] a1 = new int[]{1,2,3};

String [] a4 = new String[]{"a","b","c"};

System.out.println(a1.getClass() == a4.getClass());//编译失败 为什么?

刚才又看了看 getClass方法的API文档。

原来是在java 5之后 

a1.getClass()  返回的是一个Class<? extends int[]>类型的实例对象;

a4.getClass()  返回的是一个Class<? extends String[]>类型的实例对象。

直接让a1.getClass()a4.getClass()通过==比较肯定会造成类型不兼容的问题

如果这么写:

Class clazz1=a1.getClass(); //不会出错时因为把a1.getClass() Class<? extends int[]>进行了向上转型转成了 Class类型的

Class clazz3=a4.getClass();//不会出错时因为把a4.getClass() Class<? extends String[]>进行了向上转型转成了 Class类型的

System.out.println(clazz1 == clazz3);

其实通过equals方法来比较就可以了,也即这样写System.out.println((a1.getClass()).equals(a4.getClass()));也不会出错。

至于张老师讲课的时候,为啥直接这样写  System.out.println(a1.getClass() == a4.getClass());还能编译通过。

我个人认为可能是张老师的Eclipse使用的jdk版本在1.5之之前(1.5之前没有泛型)吧。(貌似我记得张老师头几天讲课时把这个程序的workspace的编译环境故意设置底了点)这个我只是猜想,没有再回过头去验证。

e)        总结

           i.               

1.        ==是比较两个同类型的对象的引用的地址值是否相同

2.         equals方法可以比较任意的两个对象的……是否相同。

           ii.              java API原话)getClass方法实际结果类型Class<? extends |X|>,其中 |X|表示清除表达式中的静态类型,该表达式调用 getClass

例如,以下代码片段中不需要强制转换:

Number n = 0;

Class<? extends Number> c = n.getClass();

类加载器:

1、ClassLoader类加载器:

a)        类加载器用于把硬盘上的 *.class文件加载到内存中来,然后再对它进行一些处理,处理完的结果就是字节码。而这一系列工作都是类加载器在干。

                         i.             类加载器是负责加载类的对象;

                       ii.             类加载器也可以加载*.class的普通文件

1.        通过getResource (String name)等等几个方法来加载普通文件。

b)        类加载器的用途类加载器只能加载classpath环境下的各种文件。(也即类加载器不止能加载*.class文件,也能加载非class的其他普通文件。)

                         i.             使用类加载器ClassLoader对象的getResourceAsStream(String name)方法和getResource(String name)等方法加载classpath路径环境变量下的某个文件时。

1.        这些方法里面的实参一定不能用 /打头,说明这个实参字符串表示的路径是一个相对路径相对于classpath所标示的路径

a)        如果这个文件在(classpath路径的下几层)目录中。那么这些方法的参数name就一定要写上这个下几层目录。否则在运行时,将会抛出 NullPointerException异常。

                       ii.             而对于直接通过Class对象实例的getResourceAsStream(String name)等方法得到的这个文件。这里的name实参一般情况下,可以直接写这个文件的文件名,而不用去理会这个文件位于classpath路径下的那个文件夹(java包)中。(因为一般情况下,这个文件就位于classpath路径下的某个java包中,和这个Class对象实例位于同一个包中)实例见 ReflectTest2.java文件

1.        //InputStream ips = ReflectTest2.class.getResourceAsStream(“config.properties”);//这个参数没有用 /打头,说明这个字符串表示的路径是一个相对路径相对于ReflectTest2.class文件所在的路径。使用相对路径,一定不能使用 / 打头。如果使用/ 打头了,就表示这是一个绝对路径了。

2.        InputStream ips = ReflectTest2.class.getResourceAsStream(“/cn/itcast/javaenhance/config.properties”);//这个参数用 /打头,说明这个字符串表示的路径是一个绝对路径classpath指定的路径开始的绝对路径。并且使用这个绝对路径时,必须要用 / 打头。如果没有使用/ 打头了,就表示这是一个相对路径了。

                      iii.             SSH这三种框架的加载配置文件的原理:就是使用的这个类加载器ClassLoader的方式来加载配置文件的。

                     iv.             eclipse的原理

1.        编译

a)        外部路径”默认为eclipse的"java build path"的source页签中设置的"output folder"的路径;

b)        内部路径”即为.java文件的包路径;

 

2.        执行

a)        对.java文件的“package”一项做编译检查,

b)        package中的路径必须与.java文件存放的路径完全一致;

c)        这样右键.java文件执行时,

d)        eclipse会自动根据.java文件存放的路径构建完整的包路径执行

c)        系统默认的三个的类加载器BootStrapExtClassLoaderAppClassLoader他们之间并没有什么继承关系,但是这三种加载器之间具有一种委托的上下级的关系

                         i.             比如BootStrap就不是用java语言编写的;

                       ii.             并且ExtClassLoaderAppClassLoader都是sun.misc.Lancher的内部类:  sun.misc.Launcher$AppClassLoader

sun.misc.Launcher$ExtClassLoader

                      iii.             并且ExtClassLoaderAppClassLoader都是java.net.URLClassLoader的子类

1.        java.net.URLClassLoader类是J2SE的标准类,它的父类是SecureClassLoader,而SecureClassLoader是继承自ClassLoader 类的。

                     iv.             现在整个关系应该很清楚,几乎所有的ClassLoader 实现都是继承URLClassLoader 的。(也即几乎所有的加载器,都是继承自URLClassLoader的)

内省:

1、内省

a)        JavaBean中一定要有一个不带参数的构造方法

b)        JavaBean必须是一个public或者接口

c)        JavaBean的属性必须是private

2、java7的一个新特性:

a)      可以这样定义一个map集合:

                    i.              Map map = { name:"zxx", age:18};

3、内省的几个常用类

a)        PropertyDescriptor

b)        IntroSpector

c)        BeanInfo

BeanUtils包中的类:(BeanUtils包中的BeanUtils类和PropertyUtils类是操作java bean 最常用的类了)

d)        BeanUtils

                         i.             BeanUtils的方法:

1.        copyProperties(……); //用于拷贝一个java bean上的所有属性到另一个java bean上。

2.        describe(……); //用于把一个java bean上的所有属性转换到一个Map集合里面去,并返回这个Map集合。(这个方法比较常用)

3.        populate(……); //用于把一个Map集合上的键值对(根据键和一个对应java bean上的属性间的对应关系)填充到这个java bean上的属性上去。

a)        由此可知:copyProperties方法和describe方法用于java bean的属性和Map集合之间进行相互转换!

4.        BeanUtilsgetPropertysetProperty方法不仅可以操作java bean,而且还可以操作Map集合。因为Map集合和java bean很类似!  

e)        PropertyUtils

f)          这两个类里面都有getPropertysetProperty方法。

                         i.             但是这两个类里面的这两个方法传入的参数有些不同。

1.        BeanUtils类的get属性时返回的结果字符串set属性时可以接受任意类型的对象,但通常我们使用字符串来设置一个属性。

2.        PropertyUtils类的的get属性时返回的结果这个属性的本身的数据类型的数据,set属性时只能接受这个属性的本身的数据类型的数据。

a)        比如这个属性本身是一个int型的。那么set属性时,就接受一个int型的数据;在get属性时,返回的结果为这个int型的包装类Integer类型的对象。