16天学完java

Day 01
一、    从面向过程编程到面向对象编程的思维转变
我们知道所有的计算机程序都是由两类元素组成:代码和数据。此外从概念上将讲,程序还可以以他的代码或是数据为核心进行组织编写。也就是说一些程序围绕“正在发生什么编写“,而另一些程序则围绕”谁将被影响“编写。这两种范型决定程序的构建方法。第一种方法被称为面向过程的模型,用他编写的程序都具有线性执行的特点。面向过程的模型可以认为是代码作用于数据,用C写的程序就是典型的面向过程模型。第二种方法也就是我们现在正在学习的面向对象编程,面向对象编程围绕她的数据(即对象)和为这个数据严格定义的接口来组织程序。面向对象的程序实际上就是用数据控制对代码的访问。CoreJava就是一门纯面向对象编程的语言。

二、    什么是字节码和虚拟机:
字节码是一套设计用来在Java运行时系统下执行的高度优化的指令集。该Java运行时系统称为Java虚拟机(JVM)。JVM其实就是一个字节码解释器。虚拟机将字节码解释成机器码给CPU执行,所以我们在java中通过虚拟机的这种解释执行方式来屏蔽底层操作系统的差异。
JRE = JVM+编译器
JDK= JVM+编译器+类库

三、    环境变量的设置:
需要新加的两个环境变量
1、JAVA_HOME:指名JDK的位置。
2、CLASSPATH:指名到哪里去找运行时需要用到的类代码(字节码)
原有的环境变量
1、    PATH:指名可执行程序的位置。
2、    EXPORT :将指定的环境变量声明为全局的。
我们在.bash_profile下的环境变量设置。
JAVA_HOME=/opt/jdk1.5
CLASSPATH=.
PATH=$PATH:$JAVA_HOME/bin:.
注:  “.”代表当前目录
当我们把环境变量都配置好了以后在终端敲入”java -version”命令如果出现JDK版本号信息就表示我们环境变量设置成功了。
Bin目录下放的是一些JDK命令

四、    kate工具的使用
这个就不多做描述了,大家多试试就清楚了

五、    我们的第一个Java程序
public class MyFirstJava{
        public static void main(String[] args){
            System.out.println(“Hello World”);
}
}
注:
1、我们要求类名必须和文件名一致,只不过文件名多了个.java的后坠。
2、main函数是我们整个程序的执行入口所以必须是静态公开的。
编译:javac MyFirstJava.java
编译后我们可以看到目录下多了一个MyFirstJava.class文件。这就是Java编译原文件后生成的字节码文件。
        执行:java MyFirstJava
                将字节码文件交给JVM去解释执行。
        思考:
1、为什么编译后不生成可执行文件(注:所有的可执行文件都是机器代码)
2、Java的跨平台特性(SUN口号 :一次编译到处运行);

六、    包结构
为了根据需要将不同的原文件放在不同的目录下我们引入了包。包我们可以看作就是一个存放java原文件的目录。
在源码的基础上声明一个包名:package sd0604
加包后我们用“javac MyFirstJava.java –d  .”编译后生成的字节码文件就会放在我们指定的包(目录)结构下.
如果我们想指定多级目录那么在目录明之间我们可以用.作为分隔符。
例如:package sd0604.najing.xuanwu

七、    CoreJava中的注释
1、//单行注释
2、/* */多行注释
3、/**  */文档注释
文档注释可以由java doc命令单独提取出来生成注释文档。
例:javadoc MyFirstJava.java
我们在生成的注释文件中可以打开index入口页面来查看我们刚刚生成的注释文档。
文档注释一般写在类、方法、属性定义之前
前两种注释和C++相同。
注意:1、我们可以用javadoc –help命令来查看该命令的其他用法。
2、同样我们可以用“javadoc –d 路径名”来指定生成文档注释的位置。
3、可以在文档注释中加入HTML标签来控制生成注释文档的显示格式。

八、    jar命令的用法
我们可以用“jar –cvf  m  n”命令来将文件打包成jar压缩包。
m: 要生成jar包的名字
n: 要压缩文件的文件名(可以是多个文件或一个目录)
生成的jar文件实际上就是一个普通的zip压缩文件

九、计算机编译一个java程序的过程
1、    启动JVM
2、    通过JAVA_HOME\jre\lib目录下找到对应的类
3、    如果的2不找不到则在环境变量中配置的CLASSPATH配置的路径中找类,这就是为什么我们要在CLASSPATH中配上当前路径的原因。

十、import声明的作用
    当我们要用一个JDK定义好的类时我们需要在Java程序中配上该类对应的jar包。(类似于C++中了#include预处理指令)
    例:import java.util.*;
    这里大家注意一点:由于java.lang.*包中的类是我们编程中经常要使用的,所以这个包下的类我们不用特别用import在程序中声明。但当我们要用到其他包中的类似我们就必须用import声明了。
awt:抽象窗口工具.
    如果大家想了解什么包做什么用的话大家课以看看我给大家的API 文档,上面有对所有这些包用法的解释。

十一、java中的垃圾回收器
    因为有了垃圾回收器,我们可以不用顾虑对象创建后占用系统资源的问题。我们只用负责对象的创建,而对象销毁和资源释放的问题就可以留给垃圾回收器做了。这里我们需要注意的是垃圾回收器一般只会在内存空间不够的情况下进行资源回收。

十二、java中标识符的命名规则
1、    只能以字母、下划线或”$”开头,严格区分大小写,且长度不限。
2、    类名的每个单词的首字母大写
3、    方法名属性名的第一个单词小写,以后的每个单词首字母大写
4、    所有的包结构名字都是小写
5、    常量名所有字母大写
注:第一点是必须遵守的,2~5点不遵守也不会出错,但建议大家严格遵守以上命名规范。

十三、java中的关键字和保留字
        查书

十四、java中的八中基本数据类型
1.    boolean:占1个字节
2.    byte   :占1个字节
3.    short  :占2个字节
4.    int    :占4个字节
5.    long  : 占8个字节
6.    char  : 占2个字节(可以用来保存汉字)
7.    float  : 占4个字节
8.    double : 占8个字节

十五、正负数在内存空间中的存放
正数 在内存空间中存发的是源码。
负数 在内存空间中存发的是正数源码对应的补码。
    补码:在源码的基础上取反末位加1。

十六、基本数据类型之间的转换
1、    正向过程:从低字节到高字节可以自动转换。
byte->short->int->long->float->double
注:boolean不能转。
2、    逆向过程:从高字节到低字节用强制类型转换
例:int a = (int)3.12
注:逆向转换将丢失精度。

十七、java中的转义字符
1.    表示格式控制的转义字符(如:\n \t)与C++相同。
2.    Java中用“\u四位十六进制的数字”表是将字符转换成对应的unicode编码。

十八、表达式和流程控制
        instanceof():用户判断某一个对象是否属于某一个类的实例。
        运算符:单目运算符、双目运算符、位运算符
注:1、>>>是corejava中的位移运算符,表示右移,左边空出的位以0添充。>>右移
    2、将一个数右移n位相当于将该数除以2的n次方;
3、    将一个数左移n位相当于将该数乘以2的n次方;
4、    &&、||是短路运算符(左边条件不符合时不会执行右边的判断)



Day02
一、流程控制语句
1、两路分支选择
If else 配对原则:else一定会和离他最近的且没有与别的else配对的if配对;
2、多路分支选择
    switch (byte,short,int,char){
case  xxx:
            break;
case    xxx:
            break;
default:
}
3、循环结构
3.1    for(初始化;条件;调整){语句块} 该结构在知道循环次数的时候使用
初始化语句只执行一次;
判断条件à执行语句块à执行调整à判断条件
for(;;)表示位无限循环
注:for循环中两个分号是不能省略的。
        3.2 While(条件){语句块}改结构在不知道循环次数的时候使用
            先判断后执行,调整语句在代码块中体现。
            while(1)表示为无限循化。
        3.3  Do {语句块}while(条件);同3.2;
            唯一的区别是该循环语句代码块至少要被执行一次;
            先执行后判断
        continue:提前终止本次循环直接进入下一次循环;
        3.4 java中的循环标号
        labe:for(int i=0;i<10;i++){
                    for(int a=0;a<10;a++){
                        break labe;
                    }
             }
break labe:直接跳出同标号循环层
4、条件运算符的自动类型提升问题。

二、java中的数组
1.    数组的定义
分为两部分:数组引用(声明) int[] a; int a[];
                    数组空间(初始化)a = new int[5];
2.    数组在分配存储空间后,系统会自动为数组的每个元素初始化为0;
3.    定义数组,分配存储空间和初始化数组可以放在一个语句中,如:
int[] a = {10,20,30}
对比:int[] a = new int[3];a[0] = 10;a[1] = 20;a[2] = 30;
4.    在java中一个数组就是一个对象,只要是对象就是在堆空间存放。
注:在java中只有堆空间,栈空间,代码空间。
5.    数组长度可以用 数组名.length来取得.
注:二维数组用.length取得的长度是其一维数组的长度。
6.    两个数组之间的拷贝:System.arraycopy(a,0,b,0,length)
表示将a数组从0号位置开始的length个元素依次拷贝到b数组中(从0号位置开始)。
7.    在java中二维数组本质上就是一维数组的数组。所以java中的二维数组可以是不对称的。Java中只有一维数组的内存地址空间是连续的而二维数组的空间可以不连续。
(1)、二维数组声明和初始化
            int[][] a;//声明一个二维数组
            a = new int[3][];//该二维数组包含三个一维数组对象
        而每个一维数组对象长度可以不同所以第二个【】中的长度可以不填
            a[0] = new int[5];//第一列数组长度为5
            a[1] = new int[3]; //第二列数组长度为3
        a[0][0] = 1;//将第一个数组的第一个元素初始化1;
8.    介绍一个关于数组的小技巧
在我们使用数组时,我们可以用一个index辅助变量来配合数组使用,表示其有效数据的个数,同时用来表示数组下一个可插入位置的下标。

三、    java中的对象
声明:Student s ;
这时我们只是说明s是一个能够指向Studeng类型的引用(对象变量),并没有创建一个对象。所以我们不能对s做任何操作。
初始化:s = new Student();
向系统申请一块存储空间(地址空间),该地址空间保存的是一个Student类型的数据。而s中保存的就是该地址空间的首地址。
        这里大家可能还是不太好理解,那么我们给变量来下一个定义
什么叫变量:变量就是内存空间中一块具有固定长度的,用来保存数据的地址空间。(s也是一个变量)
一个对象可以有多个引用指向。
Student[] s = new Student[3]只是相当于声明一个长度为3的Student类型的数组。
       
四、    实例变量和局部变量
实例变量:1、在一个类中,任何方法之外定义的变量;
2、从面向对象的思想来说我们又把实例变量成为一个类的属性。
3、实例变量在没有符初值时系统会自动帮我们做初始化:整型数据初始化为0,布尔型数据初始化为false,对象类型初始化为null。
局部变量:1、在方法内定义的变量叫局部变量。
2、局部变量使用前必须初始化,系统不会自动给局部变量做初始化。
3、局部变量的生命范围在他所在的代码块,在重合的作用域范围内不允许两个局部变量命名冲突。
注:局部变量与实例变量允许同名,在局部变量的作用域内,其优先级高于实例变量。我们可以用this.实例变量名以区分局部变量。


Day03
一、    java中的自动类型提升问题。
public class test1{
    public static void main(String[] args){
        byte a = 1;
        byte b = 2;
        byte c = (byte)(a+b);
        System.out.println(c);
    }
}
    二进制是无法精确的表示0.1的。
    进行高精度运算可以用java.math包中BigDecimal类中的方法。
    自动类型提升又称作隐式类型转换。

二、在java中对面向对象(OO)的要求
1.对象是客观存在的,万物皆对象。
.        (注:看不见的对象并不表示该对象不存在,比如说事件);
2. 简单性:采用面向对象方法可以使系统各部分各司其职各尽所能。
3.    复用性:对象的功能越简单其可重用性越高。
4.    弱耦合性:各司其职各尽所能。
5.    高内聚性:一个对象独立完成一个功能的能力
6.    类是一类事务的共性,是人类主观认识的一种抽象,是对象的模板。

三、面向过程与面向对象的对比
    面向过程:先有算法,后有数据结构。先考虑怎么做。
    面向对象:先有数据结构,后有算法。先考虑用什么做。

四、java中方法的声明(分为五个部分)
1.    方法的修饰符(可以有多个,且顺序无关)
2.    方法的返回值类型
3.    方法名
4.    方法的参数表
5.    方法允许抛出的列外(异常)
注:编译器只能做语法上的检查,而不能进行逻辑上的检查。
     Java中不允许有废话。

五、    java中的重载(Overload)
1、相同方法名,不同参数表。
2、方法重载时,对于参数的匹配有个向上就近原则。(这样可以节省栈空间资源);
3、为什么面向对象中要有方法重载?
       方法的重载使同一类方法由于参数造成的差异对于对象的使用者是透明的。对象的使用者只负责把参数交给对象,而具体怎么实现由对象内部决定。
4、Java中的运算符重载
java中唯一重载的运算符是String类型的“+”号,任何类型+String类型结果都为Stirng类型。

六.Java中创建对象的步骤
1、    分配空间
2、    初始化属性
3、    调用构造方法
注:构造方法不能手工调用,在对象的生命周期内构造方法只调用一次。

七、java中的构造方法
1、    特点:没有返回值,方法名与类名相同。
2、    在不写构造方法时,系统会自动生成一个无参的构造方法。
3、    请养成在每个类中自己加上无参构造方法的习惯。

八、对象和对象引用的区别
      对象好比一台电视机,对象引用好比电视机遥控。对象引用中存的是对象的地址。多个对象引用中存放的是同一个地址,表示该对象被多个对象引用所引用。

九、    this表示当前对象
谁调用该方法,在这一时刻谁就是该方法的当前对象
用this来区分实例变量和局部变量。
this()表示调用本类的其他构造方法,且只能放在一个方法中的第一行第一句。

十、    参数传递
在java方法传参过程中简单类型是按值传递,对象类型是按引用传递。
按值传递传递的是数据的副本。
    按引用传递传递的是保存该数据的地址

十一、封装
1.定义:封装指的是一个对象的内部状态对外界是透明的,对象与对象之间只关心对方有什么方法,而不关心属性。
    封装使实现的改变对架构的影响最小化。
2.原则:装使对象的属性尽可能的私有,根据需要配上相应的get/set方法,对象的方法尽可能的公开。该隐藏的一定要隐藏,该公开的一定要公开。
3.方法公开的使声明而不是实现。使方法实现的改变对架构的影    响最小化。
4.访问控制从严到宽
private  :仅本类成员可见
default  :本类+同包类可见(默认)
protected:本类+同包+不同包的子类
public   :公开
    5、完全封装:属性全部私有,并提供相应的get/set方法。


Day04
一、    继承
1.    定义:基于一个已存在的类构造一个新类。继承已存在的类就是复用这些类的方法合属性,在此基础上,还可以在新类中添加一些新的方法和属性。
2.    父类到子类是从一般到特殊的关系。
3.    继承用关键字extends
dog extends Animal :表示狗类继承了动物类
4.    Java中只允许单继承(java简单性的体现)
父子类之间的关系是树状关系。(而多继承是网状关系)
5.    父类中的私有属性可以继承但是不能访问。
也可以说父类中的私有属性子类不能继承。
6.    原则:父类放共性,子类放个性。
7.    构造方法不能被子类继承。

二、带继承关系的对象创建的过程
1.    递归的构造父类对象
2.    分配空间
3.    初始化属性
4.    调用本类的构造方法

三、super关键字
1.    Super()表示调用父类的构造方法
2.    Super()也和this一样必须放在方法的第一行第一句。
3.    Super().表示调用父类的方法或属性。例:super.m();
4.    Super可以屏蔽子类属性和父类属性重名时带来的冲突
5.    在子类的构造函数中如果没有指定调用父类的哪一个构造方法,那么就会调用父类的无参构造方法,即super()。

四、白箱复用和黑箱复用
1.白箱复用:又叫继承复用,子类会继承父类所有的东西,
从某种程度上说白箱复用破坏了封装。是一种is a的关系。
例:class Liucy{
        public void teachCpp(){
            System.out.println("Teach Cpp");
        }
        public void chimogu(){
        }
}

class Huxy extends Liucy{
}
2、黑箱复用:又叫组合复用,是一种has a的关系。
例:class Liucy{
        public void teachCpp(){
            System.out.println("Teach Cpp");
        }
        public void chimogu(){
        }
}

class Huxy {
    private Liucy liucy = new Liucy();
    public void teachCpp(){
        liucy.teachCpp();
    }
}
    原则:组合复用取代继承复用原则。
            使我们可以有机会选择该复用的功能。

五、多态
1.    定义:所谓多态是指一个对象可以有多种形态,换句话说多态使我们可以把一个子类对象看作是一个父类对象类型( 例:father A = new child() ) 。多态指的是编译时的类型变化,而运行时类型不变。
2.    多态分为两种:编译时多态和运行时多态。
编译时类型:定义时类型(主观概念)把它看作什么。
运行时类型:真实类型(客观概念) 实际上他是什么。
重载又叫编译时多态,覆盖又称运行时多态。
在方法重载的情况下,参数类型决定于编译时类型。
3.    多态的作用:在我们需要一类对象的共性时,我们可以很容易的抽取。并且可以屏蔽不同子类对象之间我们所不关心的差异。多态使我们有机会写出更通用的代码,以适应需求的不断变化
4.    多态常见的变化:
(1)、多态用在方法的参数上
(2)、多态用在方法的返回类型上
5.    运行时多态的三原则:
(1)、对象不变(改变的是主观认识)
    (2)、对于对象的调用只能限于编译时类型的方法。
(3)、在程序的运行时,动态类型判定。运行时调用运行时类型,即他调用覆盖后的方法。

六、java中的覆盖(Override)
1、    参数表、方法名必须完全相同,访问修饰符要求子类宽于父类。返回值类型在JDK1.5以前要求完全相同,
1.5以后可以父类返回一个对象a,子类返回一个该对象a的子类也是覆盖。子类方法覆盖父类方法时要求子类方法的访问修饰符宽于或等于父类的访问修饰符。
2、    为什么面向对象中要有方法覆盖?
覆盖允许子类用自己特色的方法去替换调父类已有的方法。
3、    父类中的私有方法与子类中任何方法不够成覆盖关系,
也就是说只有父类被子类继承过来的方法,才有可能与子类自己的方法构成覆盖关系。
        4、少覆盖原则:如果子类覆盖了父类过多的方法,那么我们要重
新思考一下这两个类之间到底是不是继承关系。
    注:子类的属性和父类的属性同名时叫遮盖(区覆盖)
         属性的遮盖是没有多态的。

七、关系运算符:instanceof
1.  boolean  c = a  instanceof  b;
a:对象变量;b:类名;c:逻辑型返回值。
如果可以把a对象看作是b类型,那么返回真。否则返回假。
2.    instanceof一般用于在强制类型转换之前判断对象变量是否可以强制转换为指定类型。

String [] args 命令行参数在用java命令运行程序时输入:
如:java TestOverLoad 参数1 参数2 参数3。。。。。。。


Day05
一、static修饰符
1.    可以修饰属性、方法、初始代码块,成为类变量、静态方法、静态初始化代码块。
注:初始代码块是在类中而不再任何方法之内的代码块。
2.    类变量、静态方法、静态初始化代码块与具体的某个对象无关,只与类相关,是全类公有的。在类加载时初始化。
3.    类加载:虚拟机通过CLASSPATH从磁盘上找到字节码文件,并将字节吗文件中的内容通过I/O流读到内存的过程。在虚拟机的生命周期中一个类只被加载一次。
注:Java命令的作用是启动JVM。
4.    Static定义的时一块为整个类共有的一块存储区域,其发生变化时访问到的数据都是经过变化的。
5.    为什么主方法必须是静态的?
主方法是整个应用程序的入口,JVM只能通过类名去调用主方法。
6.    类变量和静态方法可以在没有对象的情况下用:类名.方法名(或属性名)来访问。
7.    静态方法不可被覆盖(允许在子类中定义同名的静态方法,但是没有多态);父类如果是静态方法,子类不能覆盖为非静态方法。父类如果是非静态方法,子类不能覆盖为静态方法。
争论:静态方法可以覆盖但是没有多态。
思考:没有多态的覆盖叫覆盖吗?
在静态方法中不允许调用本类中的非静态成员。
8.    静态初始化代码块只在类加载的时候运行一次,以再也不执行了。所以静态代码快一般被用来初始化静态成员。
9.    不加static为动态初始化代码块,在创建对象时被调用(再构造函数之前)。

二、    什么时候类加载
第一次需要使用类信息时加载。
类加载的原则:延迟加载,能不加载就不加载。
触发类加载的几种情况:
(1)、调用静态方法时会加载静态方法真正所在的类。
例:通过子类调用父类的静态方法时,只会加载父类而不会加载子类。
(2)、调用静态初始化代码块时要加载类。
(3)、加载子类时必定会先加载父类。
(4)、构造对象的时候会加载。
(5)、调用静态属性时会加载类。
        注:如果静态属性有final修饰时,则不会加载。
                例:public static final int a =123;
但是如果上面的等式右值改成表达式(且该表达式在编译时不能确定其值)时则会加载类。
                例:public static final int a = math.PI

三、final修饰符
1.    final可以用来修饰类、属性和方法。
2.   final修饰一个属性时,该属性成为常量。
(1)对于再构造方法中利用final进行赋值时候,此时在构造之前系统设置的默认值相对于构造方法失效。
(2)对于实例常量的赋值有两次机会
    在初始化的时候通过声明赋值
    在构造的时候(构造方法里)赋值
    注:不能在声明时赋值一次,在构造时再赋值一次。
注意:当final修饰实例变量时,实例变量不会自动初始化为0;
3.    Final修饰方法时,该方法成为一个不可覆盖的方法。
如果一个方法前有修饰词private或static,则系统会自动在前面加上final。即private和static方法默认均为final方法。
4.    Final常常和static、public配合来修饰一个实例变量,表示为一个    全类公有的公开静态常量。
例:pubic static final int a = 33;
在这种情况下属性虽然公开了,但由于是一个静态常量所以并不算破坏类的封装。
5.    Final修饰类时,此类不可被继承,即final类没有子类。
一个final类中的所有方法默认全是final方法。
Fianl不能修饰构造方法,构造方法不能被继承更谈不上被子类方法覆盖。

四、    关于final的设计模式:不变模式
1、不变模式:一个对象一旦产生就不可能再修改(string就是典型的不变模式);
通过不变模式可以做到对象共享;
2、池化思想:用一个存储区域来存放一些公用资源以减少存储空间的开销。
例:在String类中有个串池(在代码区)。
(1)    如果用Stirng str = “abc”来创建一个对象时,则系统会先在串池中寻找有没有“abc”这个字符串。如果有则直接将对象指向串池中对应的地址,如果没有则在串池中创建一个“abc”字符串。
所以:String str1 = “abc”;
            String str2 = “abc”;
            Str1 = = str2 返回值是ture;他们的地址是一样的。也就是说str1和str2都指向了代码空间中相同的一个地址,而这个地址空间保存就是是字符串”abc”;

(2)    如果用String str = new String(“abc”)则直接在堆空间开辟一块存储空间用来存放”abc”这个字符串。
所以:String str1 = new String(“abc”);
            String str2 = new String(“abc”);
            Str1 = = str2 返回值是false;他们的地址是不一样的。也就是说str1和str2分别指向了堆空间中不同的两个地址,而这两个地址空间保存的都是字符串”abc”;
4、    java.lang下的StringBuffer类。
            对于字符串连接
String str=”1”+”2”+”3”+”4”;
产生:
                12
123
1234
会在串池中产生多余对象,而真正我们需要的只有最后一个对象,用这种方式进行字符串连接时,不管在时间上还是在空间上都会造成相当大的浪费。所以我们应该使用 StringBuffer(线程安全的) 或者 StringBuilder(线程不安全的)
        解决方案:
                    String s;           
                    StringBuffer sb = new StringBuffer(“1”);
                    Sb.append(“2”);
                    Sb.append(“3”);
                    Sb.append(“4”);
                    S = sb.toString();
解决后的方案比解决前在运行的时间上相差2个数量级。

五、abstract修饰符
1.    可用来修饰类、方法
2.    abstract修饰类时,则该类成为一个抽象类。抽象类不可生成对象(但可以有构造方法),必须被继承使用。
抽象类可以声明,作为编译时类型,但不能作为运行时类型。
Abstract永远不会和private,static,final同时出现。
3.    Abstract修饰方法时,则该方法成为一个抽象方法,抽象方法没有实现只有定义,由子类覆盖后实现。
比较:private void print(){};表示方法的空实现
            abstract void print();表示方法为抽象方法,没有实现
4.    抽象方法从某中意义上来说是制定了一个标准,父类并不实现,留给子类去实现。
注:抽象类中不一定要有抽象方法,但有抽象方法的类一定是抽象类。

六、    关于抽象类的设计模式:模板方法
灵活性和不变性
在下面这个例子种父类(抽象类)指定了一个标准,而子类根据自己的需求做出不同的实现。
例:/****************************************************/
public class TestTemplateMethod{
    public static void main(String[] args){
        XiaoPin x1 = new ShuoShi();
        XiaoPin x2 = new DaPuKe();
        x1.act();
        x2.act();
    }
}

abstract class XiaoPin{
    abstract void jiaoliu();
    abstract void xushi();
    abstract void gaoxiao();
    abstract void shanqing();
    public final void act(){
        jiaoliu();
        xushi();
        gaoxiao();
        shanqing();
    }
}

class ShuoShi extends XiaoPin{
    void jiaoliu(){
        System.out.println("顺口溜");
    }
    void xushi(){
        System.out.println("写书");
    }
    void gaoxiao(){
        System.out.println("打招呼");
    }
    void shanqing(){
        System.out.println("二人传");
    }
}

class DaPuKe extends XiaoPin{
    void jiaoliu(){
        System.out.println("大家好");
    }
    void xushi(){
        System.out.println("老同学见面");
    }
    void gaoxiao(){
        System.out.println("打扑克");
    }
    void shanqing(){
        System.out.println("马家军");
    }
}
/*******************************************************/



Day06
一、接口(interface)
1、    定义:接口不是类,而是一组对类需求的描述,这些类要遵从接口描述的统一格式进行定义。定义一个接口用关键字interface。
例:public interface a{……}
2、    接口是一种特殊的抽象类。在一个接口中,所有的方法为公开、抽象的方法,所有的属性都是公开、静态、常量。所以接口中的所有属性可省略修饰符:public static final,接口中所有的方法可省略修饰符:public abstract。
3、    一个类实现一个接口必须实现接口中所有的方法,否则其为一抽象类。并且在实现类中的方法要加上public(不能省略)。实现接口用关键字implements.
所谓实现一个接口就是实现接口中所有的方法。
例:class Aimple implements A{……..};
4、    一个类除了继承另一个类外(且只能继承一个类),还可以实现多个接口(接口之间用逗号分割)。这样可以实现变相的多继承。
例:class Aimple extends Arrylist implements A,B,C{…}
5、    不能用“new 接口名”来实例化一个接口,但可以声明一个接口。
6、    接口与接口之间可以多继承。
例:interface face1 extends face2,face3{}
7、    接口的作用
(1)、间接实现多继承。
用接口来实现多继承并不会增加类关系的复杂度。因为接口终归不是类,与类不在一个层次上,是在类的基础上进行再次抽象。
父类:主类型     接口:副类型
典例:相声届师父(主)和干爹(副)
(2)、允许我们为一个类定义出混合类型。
(3)、通过接口制定标准
            接        口:标准的定义  定义标准
            接口的调用者:标准的使用  使用标准
接口的实现类:标准的实现  实现标准
先有接口的定义,再有接口的使用者,最后把接口的实现者传到接口的使用者中,接口的使用者会通过接口来调用接口实现者的方法。这就是接口回调。

例:sun公司提供一套访问数据库的接口(标准),java程序员访问数据库时针对数据库接口编程。接口由各个数据库厂商负责实现。
(4)、解耦合作用:采用接口可以最大限度的做到弱耦合,将标准的实现者与标准的制定者隔离(例:我们通过JDBC接口来屏蔽底层数据库的差异)
8、    接口的编程设计原则
(1)、尽量针对接口编程(能用接口就尽量用接口)
(2)、接口隔离原则(用若干个小接口取代一个大接口)
这样可以只暴露想暴露的方法,实现一个更高层次的封装。
9、    注意点:
(1)、一个文件只能有一个public接口,且与文件名相同。
(2)、在一个文件中不能同时定义一个public接口和一个public类。
(3)、接口与类之间只有实现关系,没有继承关系;
     类(抽象类)与类之间只有继承关系没有实现关系。接口与接口之间只有继承关系,且允许多继承。
(4)、接口中可以不写public,但在子类实现接口的过程中public不可省略。

二、接口 VS 抽象类
1、接口中不能有具体的实现,但抽象类可以。
2、一个类要实现一个接口必须实现其里面所有的方法,而抽象类不必。
3、通过接口可以实现多继承,而抽象类做不到。
4、接口不能有构造方法,而抽象类可以。
5、实体类与接口之间只有实现关系,而实体类与抽象类只有继承关系。

三、Object类
1、    object类是类层次结构的根类,他是所有类默认的父类。
2、    object类中的三个方法。
(1)、finalize()
        当一个对象被垃圾收集的时候,最后会由JVM调用这个对象的finalize方法;
        注意:这个方法一般不用,也不能将释放资源的代码放在这个方法里;
(2)、toString()
        返回一个对象的字符串表示形式。打印一个对象其实就是打印这个对象toString方法的返回值。
        我们可以在自己的类时覆盖toString()方法,从而打印我们需要的数据。Public String toString(){……}
 (3)、equals(Object o)
        该方法用来判断对象的值是否相等。但前提是类中覆盖了equals方法。Object类中的equals方法判断的其实还是地址。这里注意:String类已经覆盖了equals方法了,所以我们能使用equals来判断String对象的值是否相等。
    下面是覆盖equals方法的标准流程:
    public Boolean equals(Object o){
    /**第一步:现判断两个对象地址是否相等*/
        if(this = = o)  return   true;
    /**第二步:如果参数是null的话直接返回false;*/
        if(o = = null)  return   false;
    /**第三步:如果两个对象不是同一个类型直接返回false*/
        if(  !(o  instanceof  Student)  )  return false;
    /**第四步:将待比较对象强转成指定类型,然后自定义比较规则*/
        Student s = (Student)o;
        If(s.name.equals(this.name)&&s.age==this.age)
return  true;
else return false
    }
(4)、equals的特性:自反性、对称性、一致性、传递性。


Day07
一、封装类
JAVA 为每一个简单数据类型提供了一个封装类,使每个简单数据类型可以被Object 来装载。
除了int 和char,其余类型首字母大写即成封装类
int            Integer
char        Character
int Integer String之间的类型转换(最常用的)
int a =12;
int      到   Integer         Integer aa = new Integer(a);
Integer  到   int          int  i = aa.intValue();
Int      到   String       String  str = String.valueOf(i);
String   到   int          int  ii = Integer.parseInt(str);
Integer  到  String        String  str = aa.toString()
 String   到   Integer       Integer bb = Integer.valueOf(str)

二、    内部类(非重点)
1.定义:定义在其他类中的类,叫内部类。内部类是一种编译时的语法。编译后生成的两个类时独立的两个类。内部类配合接口使用,来强制做到弱耦合(局部内部类,或私有成员内部类)。
2.内部类存在的意义在于可以自由的访问外部类的任何成员(包括私有成员),所有使用内部类的地方都可以不用内部类,使用内部类可以使程序更加的简洁(以牺牲程序的可读性为代价),便于命名规范和划分层次结构。
3.内部类作为外部类的一个成员,并且依附于外部类而存在的。
4.内部类可为静态,可用PROTECTED 和PRIVATE 修饰。(而外部类不可以:外部类只能使用PUBLIC和DEFAULT)。
5.内部类的分类:成员内部类、局部内部类、静态内部类、匿名内部类。
① 成员内部类:作为外部类的一个成员存在,与外部类的属性、方法并列。
内部类和外部类的实例变量可以共存。
在内部类中访问实例变量:this.属性
在内部类访问外部类的实例变量:外部类名.this.属性。
对于一个名为outer 的外部类和其内部定义的名为inner 的内部类。编译完成后出现outer.class 和outer$inner.class 两类。
成员内部类不可以有静态属性,这是因为静态属性是在加载类的时候创建,这个时候内部类还没有被创建。
如果在外部类的外部访问内部类,使用out.inner.
建立内部类对象时应注意:
在外部类的内部可以直接使用inner s=new inner();(因为外部类知道inner 是哪个类,所以可以生成对象。)
而在外部类的外部,要生成(new)一个内部类对象,需要首先建立一个外部类对象(外部类可用),然后在生成一个内部类对象。
Outer.Inner in=Outer.new.Inner()。
相当于:Outer out = new Outer();
Outer.Inner in = out.new Inner();
错误的定义方式:
Outer.Inner in=new Outer.Inner()。
② 局部内部类:在方法中定义的内部类称为局部内部类。
与局部变量类似,在局部内部类前不加修饰符public 和private,其范围为定义它的代码块。
注意:局部内部类不仅可以访问外部类实例变量,还可以访问外部类的局部变量(但此时要求外部类的局部变量必须为final)
在类外不可直接生成局部内部类(保证局部内部类对外是不可见的)。
要想使用局部内部类时需要生成对象,对象调用方法,在方法中才能调用其局部内部类。
③ 静态内部类:(注意:前三种内部类与变量类似,所以可以对照参考变量)
静态内部类定义在类中,任何方法外,用static 定义。
静态内部类只能访问外部类的静态成员。
生成(new)一个静态内部类不需要外部类成员:这是静态内部类和成员内部类的区别。静态内部类的对象可以直接生成:
Outer.Inner in=new Outer.Inner();
对比成员内部类:Outer.Inner in = Outer.new Inner();
而不需要通过生成外部类对象来生成。这样实际上使静态内部类成为了一个顶级类。
静态内部类不可用private 来进行定义。例子:
对于两个类,拥有相同的方法:
/*********************************************************/
public class TestRobot{
    public static void main(String[] args){
        Robot r = new Robot();
        r.run();
        r.getHeart().run();
    }
}

abstract class People{
    abstract void run();
}

interface Machine{
    void run();
}

class Robot extends People{
    class Heart implements Machine{
        public void run(){
            System.out.println("发动机跑");
        }
    }
    public void run(){
        System.out.println("机器人跑");
    }
    public Machine getHeart(){
        return new Heart();
    }
}
/*************************************************************************/
此时run()不可直接实现。
注意:当类与接口(或者是接口与接口)发生方法命名冲突的时候,此时必须使用内部类来实现。这是唯一一种必须使用内部类的情况。用接口不能完全地实现多继承,用接口配合内部类才能实现真正的多继承。
④ 匿名内部类:
【1】    匿名内部类是一种特殊的局部内部类,它是通过匿名类实现接口。
【2】    不同的是他是用一种隐含的方式实现一个接口或继承一个类,而且他只需要一个对象
【3】    在继承这个类是,根本就没有打算添加任何方法。
【4】    匿名内部类大部分情况都是为了实现接口的回调。
注:一个匿名内部类一定是在new 的后面,用其隐含实现一个接口或实现一个类,没有类名,根据多态,我们使用其父类名。
因其为局部内部类,那么局部内部类的所有限制都对其生效。
匿名内部类是唯一一种无构造方法类。
注:这是因为构造器的名字必须合类名相同,而匿名内部类没有类名。
匿名内部类在编译的时候由系统自动起名Out$1.class。
因匿名内部类无构造方法,所以其使用范围非常的有限。
接口+内部类才能真正实现多继承。
一个关于匿名内部类的例子:
/******************************************************/
public class test{
    public static void main(String[] args){
        B.print(new A(){
                public void getConnection(){
                    System.out.println("Connection....");
                }
        });
    }
}

interface A{
    void getConnection();
}

class B{
    public static void print(A a){
        a.getConnection();
    }
}
/******************************************************/

三、    异常 Exception
1.    概念: JAVA 会将所有的错误封装成为一个对象,其    根本父类为Throwable。异常处理可以提高我们系统的容错性。
Throwable 有两个子类:Error 和Exception。
Error:一般是底层的不可恢复的错误。
Object
                   ↑
               Throwable
                   ↑
           |ˉˉˉˉˉˉˉˉ|
         Error          Exception
                           ↑
                     |ˉˉˉˉˉˉˉ|
              RuntimeException   非Runtime exception

2.    Exception分类:Runtime exception(未检查异常)和
非Runtime exception(已检查异常)。
未检查异常是因为程序员没有进行必要的检查,因为他的疏忽和错误而引起的异常。一定是属于虚拟机内部的异常(比如空指针)。
几个常见的未检查异常:
1)    java.lang.ArithmeticException 
如:分母为0;
2)    java.lang.NullPointerException
如:空指针操作;
3)    java.lang.ArrayIndexoutofBoundsExceptio
如:数组越界;
4)    java.lang. ClassCastException
如:类型转换异常;
已检查异常是不可避免的,对于已检查异常必须处理。

        3、异常对象的传递。
        当一个方法中出现了异常而又没做任何处理,那么这个方法会返回该异常对象。依次向上层调用者传递,直到传到JVM,虚拟机终止运行。
4、如何来处理异常(这里主要是针对已检查异常)
【1】    throws 消极处理异常的方式。
方法名(参数表)throws  后面接要往上层抛的异常。
表示该方法对指定的异常不作任何处理,直接抛往上一层。
【2】    积极处理方式try、catch
try {可能出现错误的代码块} catch(exception e){进行处理的代码} ;
一个异常捕获只会匹配一次try,catch.
一个异常一旦被捕获就不存在了。
Catch中要求必须先捕获子类异常再捕获父类异常。
【3】    finally (紧接在catch代码块后面)
finally后的代码块是无论如何都会被执行的(除非虚拟机退出),所以在finally后的代码快里我们一般写的是释放资源的代码。
Public static int fn(int b){
        Try{
            Return b/2;
        }catch(Exception e){
            return 0;
        }finally{
            return b;
}
}
返回的结果是一定是b;
5、    自定义异常(与一般异常的用法没有区别)
class MyException extends Exception{
    public MyException(String message){
        super(message);
    }
    public MyException(){}
}           
    6、如何控制try的范围:根据操作的连动性和相关性,如果前面的程序代码块抛出的错误影响了后面程序代码的运行,那么这个我们就说这两个程序代码存在关联,应该放在同一个try中。
             7、不允许子类比父类抛出更多的异常。
            8、断言:只能用于代码调试时用。(一般没什么用)
                一个关于断言的列子:
        /******************************************************/
public class TestAssertion {
    public static void main(String[] args){
        int i = Integer.parseInt(args[0]);
        assert i==1:"ABCDEFG";
/*
断言语句(表示断言该boolean语句返回值一定为真,如果断言结果为false就会报Error错误)
        ":"后面跟出现断言错误时要打印的断言信息。
        */
        System.out.println(i);
    }
}

//java -source 1.4 TestAssertion.java 
//表示用1.4的新特性来编译该程序。
//java -ea TestAssertion 0            
//表示运行时要用到断言工具
   
/********************************************************/










Day08
《集合框架》
Collection接口
           
List接口                          Set接口

    Vector    ArrayList   LinkedList  HashSet   SortedSet接口

                                                                    TreeSet

Map接口

                        HashMap       SortedMap接口

                                                    TreeMap


一、    集合:集合是一个用于管理其他多个对象的对象
1、Collection 接口:集合中每一个元素为一个对象,这个接口将这些对象组织在一起,形成一维结构。
2、List      接口:代表按照元素一定的相关顺序来组织(在这个序列中顺序是主要的),List 接口中数据可重复。
3、Set      接口:是数学中集合的概念:其元素无序,且不可重复。(正好与List 对应)
4、SortedSet 接口 :会按照数字将元素排列,为“可排序集合”。
5、Map     接口 :接口中每一个元素不是一个对象,而是一个键对象和值对象组成的键值对(Key-Value)。
6、SortedMap接口:如果一个Map 可以根据key 值排序,则称其为SortedMap。

注意:在“集合框架”中,Map 和Collection 没有任何亲缘关系。
?Map 的典型应用是访问按关键字存储的值。它支持一系列集合操作的全部,但操作的是键-值对,而不是单个独立的元素。因此Map 需要支持get() 和put() 的基本操作,而Set 不需要。
?返回Map 对象的Set 视图的方法:
 Set set = aMap.keySet()
     
《常用集合列表》
    List    Set    SortedSet    Map    SortedMap
存放元素    Object    Object    Object    Object(key)—Object(value)    Object(key)—Object(value)
存放顺序    有序    无序    无序    Key无序    无序,有排序
元素可否重复    可    不可    不可    Key不可,value可    Key不可,value可
遍历方式    迭代    迭代    迭代    对Key迭代    对Key迭代
排序方式    Collections.sort()    SortedSet    已排序    SortedMap    已对键值排序
各自实现类    ArrayListLinkedList    HashSet    TreeSet    HashMap    TreeMap

注:以上有序的意思是指输出的顺序与输入元素的顺序一致
    HashSet、HashMap通过hashCode(),equals()来判断重复元素
    在java中指定排序规则的方式只有两种:1、实现java.util包下的Comparator接口
                                                       2、实现java.lang包下的Comparable接口
 

二、    迭代器:Iterator
1、使用Iterator接口方法,您可以从头至尾遍历集合,并安全的从底层Collection中除去元素
2、remove() 方法可由底层集合有选择的支持。当底层集合调用并支持该方法时,最近一次next() 调用返回的元素就被除去
3、Collection 接口的iterator() 方法返回一个Iterator
4、Iterator中的hasNext()方法表用于判断元素右边是否还有数据,返回True 说明有。然后就可以调用next()动作。
5、Iterator中的next()方法会将游标移到下一个元素,并把它所跨过的元素返回。(这样就可以对元素进行遍历)
6、用于常规Collection 的Iterator 接口代码如下:
    /*迭代遍历*/
        List l = new ArrayList();
        Iterator it = l.iterator();
        while(it.hasNext()){
            Object o = it.next();
            System.out.println(o);
        }
注:工具类是指所有的方法都是公开静态方法的类。
            Java.util.collections就是一个工具类;

三、    对集合的排序
1、    我们可以用Java.util.collections中的sort(List l)方法对指定的List集合进行排序;但是如果List中存放的是自定义对象时,这个方法就行不通了,必须实现Comparable接口并且指定排序规则。
        这里我们再来看一下sort(List l)方法的内部实现;
/**********************************************************/
class Collections2{
    public static void sort(List l){
        for(int i=0;i            for(int j=i+1;j                Object o1 = l.get(i);
                Object o2 = l.get(j);
                Comparable c1 = (Comparable)o1;
                Comparable c2 = (Comparable)o2;
                if(c1.compareTo(c2)>0){
                    Collections.swap(l,i,j);
                }
            }
        }
    }
}
    注:其实用的算法就是个冒泡排序。
/******************************************************/
2、    实现Java.lang.Comparable接口,其实就是实现他的
public int compareTo(Object o)方法;
比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。

其规则是当前对象与o 对象进行比较,其返回一个int 值,系统根据此值来进行排序。
如当前对象>o 对象,则返回值>0;
如当前对象=o 对象,则返回值=0;
如当前对象
注意:String类型已经实现了这个接口,所以可以直接排序;
/******************************************************/
class Student implements Comparable{
    private String name;
    private int age;
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public int compareTo(Object o) {
        Student s = (Student)o;
        return s.age-this.age;
    }
}
/******************************************************/

四、    ArrayList和LinkedList集合
1、ArrayList 底层是object 数组,所以ArrayList 具有数组的查询速度快的优点以及增删速度慢的缺点。
    Vector 底层实现也是数组,但他是一个线程安全的重量级组件。
2、而在LinkedList 的底层是一种双向循环链表。在此链表上每一个数据节点都由三部分组成:前指针(指向前面的节点的位置),数据,后指针(指向后面的节点的位置)。最后一个节点的后指针指向第一个节点的前指针,形成一个循环。
3、双向循环链表的查询效率低但是增删效率高。所以LinkedList 具有查询效率低但增删效率高的特点。
4、ArrayList 和LinkedList 在用法上没有区别,但是在功能上还是有区别的。
LinkedList 经常用在增删操作较多而查询操作很少的情况下:队列和堆栈。
队列:先进先出的数据结构。
堆栈:后进先出的数据结构。
(堆栈就是一种只有增删没有查询的数据结构)
注意:使用堆栈的时候一定不能提供方法让不是最后一个元素的元素获得出栈的机会。
LinkedList 提供以下方法:(ArrayList 无此类方法)
addFirst();
removeFirst();
addLast();
removeLast();
在堆栈中,push 为入栈操作,pop 为出栈操作。
Push 用addFirst();pop 用removeFirst(),实现后进先出。
用isEmpty()--其父类的方法,来判断栈是否为空。
在队列中,put 为入队列操作,get 为出队列操作。
Put 用addFirst(),get 用removeLast()实现队列。
List 接口的实现类(Vector)(与ArrayList 相似,区别是Vector 是重量级的组件,使用使消耗的资源比
较多。)
结论:在考虑并发的情况下用Vector(保证线程的安全)。
在不考虑并发的情况下用ArrayList(不能保证线程的安全)。
5、面试经验(知识点):
java.util.stack(stack 即为堆栈)的父类为Vector。可是stack 的父类是最不应该为Vector 的。因为Vector的底层是数组,且Vector 有get 方法(意味着它可能访问到并不属于最后一个位置元素的其他元素,很不安全)。
对于堆栈和队列只能用push 类和get 类。
Stack 类以后不要轻易使用。
!!!实现堆栈一定要用LinkedList。
(在JAVA1.5 中,collection 有queue 来实现队列。)

五、    HashSet集合
1.、HashSet是无序的,没有下标这个概念。HashSet集合中元素不可重复(元素的内容不可重复);
2、HashSet 底层用的也是数组。
3、HashSet如何保证元素不重复?Hash算法和equals方法。
当向数组中利用add(Object o)添加对象的时候,系统先找对象的hashCode:
int hc=o.hashCode(); 返回的hashCode 为整数值。
Int I=hc%n;(n 为数组的长度),取得余数后,利用余数向数组中相应的位置添加数据,以n 为6 为例,
如果I=0 则放在数组a[0]位置,如果I=1,则放在数组a[1]位置。如果equals()返回的值为true,则说明数据重复。如果equals()返回的值为false,则再找其他的位置进行比较。这样的机制就导致两个相同的对象有可能重复地添加到数组中,因为他们的hashCode 不同。如果我们能够使两个相同的对象具有相同hashcode,才能在equals()返回为真。
在实例中,定义student 对象时覆盖它的hashcode。
因为String 类是自动覆盖的,所以当比较String 类的对象的时候,就不会出现有两个相同的string 对象的情况。
现在,在大部分的JDK 中,都已经要求覆盖了hashCode。
结论:如将自定义类用hashSet 来添加对象,一定要覆盖hashcode()和equals(),覆盖的原则是保证当两个对象hashcode 返回相同的整数,而且equals()返回值为True。
如果偷懒,没有设定equals(),就会造成返回hashCode 虽然结果相同,但在程序执行的过程中会多次地调用equals(),从而影响程序执行的效率。
我们要保证相同对象的返回的hashCode 一定相同,也要保证不相同的对象的hashCode 尽可能不同(因为数组的边界性,hashCode 还是可能相同的)。例子:
public int hashCode(){
return name.hashcode()+age;
}

六、    TreeSet集合
1、  TreeSet是SortedSet的实现类TreeSet通过实现Comparable接口来实现元素不重复。
2、    TreeSet由于每次插入元素时都会进行一次排序,因此效率不高。
3、    java.lang.ClassCastException是类型转换异常。
4、    在我们给一个类用CompareTo()实现排序规则时
5、    从集合中以有序的方式抽取元素时,可用TreeSet,添加到TreeSet 的元素必须是可排序的。“集合框架”添加对Comparable 元素的支持。一般说来,先把元素添加到HashSet,再把集合转换为TreeSet 来进行有序遍历会更快。

Day09
一、    HashMap集合
1.    HashMap就是用hash算法来实现的Map
2.    在实际开发中一般不会用自定义的类型作为Map的Key。做Key的无非是八中封装类。
3.    HashMap的三组操作:
【1】改变操作允许您从映射中添加和除去键-值对。键和值都可以为null。但是,您不能把Map 作为一个键或值添加给自身。
–Object put(Object key, Object value)
–Object remove(Object key)
–void clear()
         【2】查询操作允许您检查映射内容:
–Object get(Object key)
–intsize()
–boolean isEmpty()
         【3】最后一组方法允许您把键或值的组作为集合来处理。
–public Set KeySet();
–public Collection values()
4、    HashMap和HashTable的区别等同于ArrayList和Vector的区别。只不过HashTable中的Key和Value不能为空,而HashMap可以。
5、    HashMap 底层也是用数组,HashSet 底层实际上也是HashMap,HashSet类中有HashMap 属性(我们如何在API 中查属性)。HashSet 实际上为(key.null)类型的HashMap。有key 值而没有value 值。

二、HashMap 类和TreeMap 类
?集合框架提供两种常规Map 实现:HashMap和TreeMap。
?在Map 中插入、删除和定位元素,HashMap 是最好选择。
?如果要按顺序遍历键,那么TreeMap 会更好。
?根据集合大小,先把元素添加到HashMap,再把这种映射转换成一个用于有序键遍历的TreeMap 可能更快。
?使用HashMap 要求添加的键类明确定义了hashCode() 实现。
?有了TreeMap 实现,添加到映射的元素一定是可排序的
?HashMap和TreeMap 都实现Cloneable 接口。

三、图型界面(不重要)
1、Awt:抽象窗口工具箱,它由三部分组成:
①组件:界面元素;
②容器:装载组件的容器(例如窗体);
③布局管理器:负责决定容器中组件的摆放位置。
2、图形界面的应用分四步:
① 选择一个容器:
⑴window:带标题的容器(如Frame);
⑵Panel:面板通过add()向容器中添加组件。
注:Panel不能作为顶层容器。
Java 的图形界面依然是跨平台的。但是在调用了一个窗体之后只生成一个窗体,没有事件的处理,关闭按钮并不工作。此时只能使用CTRL+C 终止程序。
②设置一个布局管理器:用setLayout();
③向容器中添加组件;
jdk1.4用getContentPare()方法添加主件。
③ 添加组件的事务处理。
Panel 也是一种容器:但是不可见的。在设置容易的时候不要忘记设置它们的可见性。
Panel pan=new Panel;
Fp.setLayout(null);表示不要布局管理器。
3、五种布局管理器:
(1)、Flow Layout(流式布局):按照组件添加到容器中的顺序,顺序排放组件位置。默认为水平排列,如果越界那么会向下排列。排列的位置随着容器大小的改变而改变。
Panel 默认的布局管理器为Flow Layout。
(2)、BorderLayout:会将容器非常五个区域:东西南北中。
语句:
Button b1=new Botton(“north”);//botton 上的文字
f.add(b1,”North”);//表示b1 这个botton 放在north 位置
注:一个区域只能放置一个组件,如果想在一个区域放置多个组件就需要使用Panel 来装载。
Frame 和Dialog 的默认布局管理器是Border Layout。
(3)、Grid Layout(网格布局管理器):将容器生成等长等大的条列格,每个块中放置一个组件。
f.setLayout GridLayout(5,2,10,10)//表示条列格为5 行2 类,后面为格间距。
(4)、CardLayout(卡片布局管理器):一个容器可以放置多个组件,但每次只有一个组件可见(组件重叠)。
使用first(),last(),next()可以决定哪个组件可见。可以用于将一系列的面板有顺序地呈现给用户。
(5)、GridBag Layout(复杂的网格布局管理器):在Grid 中可指定一个组件占据多行多列,GridBag 的设置非常的烦琐。
注:添加滚动条:JScrollPane jsp = new JScrollPane(ll);
4、常用的组件:
    (1)、JTextArea:用作多行文本域
    (2)、JTextField:作单行文

你可能感兴趣的:(Java)