Java快车读书笔记

办公自动化:OA      客户关系管理:CRM
人力资源:HR       企业资源计划:ERP
知识管理:KM       供应链管理:SCM
企业设备管理系统:EAM   产品生命周期管理:PLM
面向服务体系架构:SOA   商业智能:BI
项目管理:PM        流程管理:WorkFlow

 

文本型:char——char类型用来表示单个字符。一个char代表一个16-bit无符号的(不分正负)Unicode字符,一个char字符必须包含在单引号内。
注意:“a”表示是字符串(string),而'a'表示的是字符类型(char)

 

第一章:Java入门

一:Java分三个版本:Java标准版(JSE),Java微缩版(JME)、Java企业版(JEE)

二:Java的运行过程

1:编写代码
2:编译——机器并不认识我们写的java代码,需要进行编译成字节码,编译后的文件叫做class文件
3:类装载ClassLoader——类装载的功能是为执行程序寻找和装载所需要的类。
ClassLoader能够加强代码的安全性,主要方式是:把本机上的类和网络资源类相分离,在调入类的时候进行检查,因而可以限制任何”特洛伊木马“的应用
4:字节码(byte-code)校验——对class文件的代码进行校验,保证代码的安全性。所有源于网络的类文件都要经过字节码校验器。字节码校验器对程序代码进行四遍校验,这可保证代码符合JVM规范且不破坏系统的完整性。如果校验后未返回出错信息,则以下各点可以被保证:
1)类符合JVM规范的类文件格式
2)无访问限制异常
3)代码未引起操作数栈上溢或下溢
4)所有操作代码的参数类型将总是正确的
5)无非法数据转换发生,如将整数转换为对象引用
6)对象域访问是合法的

5:解释——机器也不能忍受class文件,还需要被解释器进行解释

6:运行——最后由运行环境中的Runtime对代码进行运行

7:注释——/* */ 多行注释  /**  */  文档注释
常用的javadoc标记:
@author:作者    @version:版本
@deprecated:不推荐使用的方法  @param:方法的参数类型
@return:方法的返回类型  @see:“参见”,用于指定参考的内容
@exception:抛出的异常  @throws:抛出的异常,和exception同义

8:java编码约定
1)class——类名应该是名词,大小写可混用,但首字母大写
2)interface——接口大小写规则与类名相同
3)method——方法名应该是动词,大小写可以混用,首字母小写。每个方法名内,大写字母将词分隔并限制使用下划线
4)variables——所以变量都可以大小写混用,但首字母小写。词由大写字母分隔,限制用下划线、美元符号($),因为这个字符对内部类有特殊含义。变量应该代表一定的含义,尽量避免使用单个字符,除非是临时的变量(如i,k,j作为循环控制变量)
5)constant——常量应该全部大写并用下划线将词分割
6)control structures——当语句是控制结构的一部分时,即使是单个语句也应使用{}将语句封闭
7)blank——java程序中任何数量的空格都是允许的,但标识符中的空格是错误的,字符串中的空格是有效的
8)spacing——每行只写一个语句并使用四个缩进的空格使你的代码更易阅读
9)comments——用注释来说明那些不明显的代码段落

 

三:java技术三大特性

1:虚拟机。它是java平台无关性的保证。基本功能如下:
1)通过ClassLoader寻找和装载class文件
2)解释字节码成为指令并执行,提供class文件的运行环境
3)进行运行期间垃圾回收
4)提供与硬件交互的平台

JVM的代码格式由紧缩有效的字节码构成。JVM为下列各项做出了定义:
1)指令集(相当于中央处理器[CPU])
2)寄存器
3)类文件格式
4)栈
5)垃圾收集堆
6)存储区

第二章:Java基础

1:++x 因为++在前面,所以先加后用
     x++ 因为++在后面,所以先用后加

2:包——物理上就是一个文件夹,逻辑上代表一个分类的概念
1)包将包含类代码的文件组织起来,易于查找和使用适当的类
2)不止包含类和接口,还能包含其他包,形成层次的包空间
3)有助于避免命名冲突。
4)控制代码访问权限
2.1:JDK中常用的包:
1)java.lang——包含一些java语言的核心类,包含构成java语言设计基础的类。最重要的类是:Object(单根)
2)java.awt——包含了构成抽象窗口工具集(abstract window toolkits)的多个类,用来构建和管理应用程序的图形用户界面(GUI)
3)javax.swing——完全java版的图形用户界面(GUI)解决方案,提供了完备的组件,可以应对复杂的桌面系统构建
4)java.net——包含执行与网络相关的操作的类。如:URL,Socket,ServerSocket等
5)java.io——包含能提供多种输入/输出功能的类
6)java.util——包含一些实用工具类,如定义系统特性、使用与日期日历相关的方法。还有重要的集合框架
2.2:代码中如何表达包——java语言使用package语句来实现包的定义。package语句必须作为java源文件的非注释语句的第一天语句,指明该文件中定义的类所在的包。如缺省该语句,则指定为无名包。
语法格式:package pkg1[.pkg2[.pkg3]];//[]表示可选

2.3:编译和生成包——如果在程序Testjava中已经定义了包 p1,就必须将编译生成的字节码文件Test.class保存在于包同名的子目录中:
1)直接编译:  javac Test.java    
编译器会在当前目录下生成Test.class文件,再手动创建一个名为p1的文件夹,将Test.class复制到该p1目录下

2)带包编译——带包编译是简化的编译命令:  
A:javac -d .\ Test.java
编译器会自动在当前目录下建立一个子目录p1,并将生成的.class文件自动保存到p1文件夹下
B:javac -d .\test\  Test.java
编译器会自动在当前目录下的test文件夹中建立一个子目录p1,并将生成的.class文件自动保存到p1文件夹下。前提是当前目录下必须有test文件夹,否则报错:“未找到目录:.\test\”
C:javac -d D:\test\  Test.java

3:析构方法——当垃圾回收器将要释放无用对象的内存时,先调用该对象的finalize()方法。如果在程序终止前垃圾回收器始终没有执行垃圾回收操作,那么垃圾回收器将始终不会调用无用对象的finalize()方法。java的基类Object基类中提供了protected类型的finalize方法
java虚拟机的垃圾回收操作对程序完全是透明的,因此程序无法预料某个无用对象的finalize()方法何时被调用。如果一个程序只占用少量内存,没有造成严重的内存需求,垃圾回收器可能没有释放那些对象占用的内存,因此这些对象的finalize方法还没有被调用,程序就终止了
程序即使是显示调用System.gc()或Runtime.gc()方法,也不能保证垃圾回收操作一定执行,也就不能保证finalize()方法一定被调用。垃圾回收器执行finalize方法时,如果出现异常,垃圾回收器不会报告异常

4:“在Java里面参数传递都是按值传递”这句话的意思是:按值传递是传递的值的拷贝,按引用传递其实传递的是引用的地址值,所以统称按值传递

在Java里面只有基本类型和按照下面这种定义方式的String是按值传递,其他的都是按引用传递。就是直接使用双引号定义字符串方式:String str = "Java 快车";

5.1:包装类——java语言中的8种基本数据类型并不支持面向对象的编程机制。为解决此问题,java语言引入了封装类的概念,在JDK中针对各种基本数据类型分别定义相应的引用类型,并称之为包装类(Wrapper Classes)
基本类型的包装类:如bool对应Boolean

5.2:自动包装和解包

自动包装——把基础数据类型自动封装并转换成对应的包装类对象
自动解包——把包装类的对象自动解包并转换成对应的基础数据类型

Integer a1 = 5;//自动包装
int a2 = new Integer(5);//自动解包

 

第三章——高级类特性

1:初始化子类必须先初始化父类

2:构造方法不能被继承

3:方法的覆盖于重载

3.1:方法的覆盖(Overridden Methods)——子类创建一个与父类方法有不同功能的方法,但是具有相同的:名称、返回类型、参数列表

规则——new 谁就调用谁的方法

3.2:方法的重载——在同一个Java类中(包括父类),如果出现了方法名称相同,而参数列表不同的情况就叫重载

3.3:多态性——instanceof运算符判断一个变量所实际引用的对象的类型(相当于C#中的is)

4.1:内部类——Inner Class
1)嵌套类(内部类)可以体现逻辑上的从属关系,同时对于其他类可以控制内部类对外不可见等
2)外部类的成员变量作用域是整个外部类,包括嵌套类,但外部类不能访问嵌套类的private成员
3)逻辑上相关的类可以在一起,可以有效的实现信息隐藏
4)内部类可以直接访问外部类的成员,由此可以实现多继承
5)编译后,内部类也被编译成单独的类,不过名称为outclass$inclass形式

4.2:匿名内部类——new AClass(){..定义..}

5:java的内存分配——java程序运行时的内存结构分成:方法区、栈内存、堆内存、本地方法栈

5.1:方法区——方法区存放装载的类数据信息包括:
1):基本信息——
    A:每个类的全限定名    B:每个类的直接超类的全限定名(可约束类型转换)
    C:该类是类还是接口    D:该类型的访问修饰符
    E:直接超接口的全限定名的有序列表
2):每个已装载类的详细信息:
    A:运行时常量池:存放该类型所用的一切常量(直接常量和对其他类型、字段、方法的符号引用)它们以数组形式通过索引被访问,是外部调用与类联系及类型对象化的桥梁。它是类文件(字节码)常量池的运行时表示(还有一种静态常量池,在字节码文件中)
    B:字段信息:类中声明的每一个字段的信息(名,类型,修饰符)
    C:方法信息:类中声明的每一个方法的信息(名,返回类型,参数类型,修饰符,方法的字节码和异常表)
    D:静态变量
    E:到类classloader的引用:即到该类的类装载器的引用
    F:到类class的引用:虚拟机为每一个被装载的类型创建一个class实例,用来代表资格被装载的类

5.2:栈内存——Java栈内存以帧的形式存放本地方法的调用状态。每调用一个方法就将对应该方法的方法帧压入java栈,成为当前方法帧。调用结束(返回)时就弹出该帧。
编译器将源代码编译成字节码(.class)时,就已经将各种类型的方法的局部变量,操作数栈大小确定并放在字节码中,随着类一并装载入方法区。当调用方法时,通过访问方法区中的类的信息,得到局部变量以及操作数栈的大小。也就是说:在方法定义的一些基本类型的变量和对象的引用变量都再方法的栈内存中分配,当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量所分配的内存空间。

栈内存的构成:局部变量区、操作数栈、帧数据区

5.3:堆内存——堆内存用来存放由new创建的对象和数组。在堆中分配的内存,由java虚拟机的自动垃圾回收管理。在堆中产生了一个数组或对象后,还可以在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中这个变量就成了数组或对象的引用变量
5.3.1:栈内存和堆内存比较——栈与堆都是java用来在内存中存放数据的地方。与C++不同,java自动管理栈和堆,程序员不能直接设置栈和堆。
Java的堆是一个运行时数据区,对象从中分配空间。堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的。java垃圾收集器会自动收走这些不再使用的数据。缺点:由于要在运行时动态分配内存,存取速度较慢
栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。缺点:存在栈中的数据大小和生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量(int,short,longbyte,float,double,boolean,char)和对象句柄。栈的重要特殊性:数据共享。假如我们同时定义:
int a = 3; int b = 3;
编译器会先处理int a=3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没有找到,就将3存放进来,然后将a指向这个3。接着处理int b=3;在创建b的引用变量后,因为栈中已经有3这个值了,便将b直接指向3。内存示意图如下:


注意这种数据共享与两个对象的引用同时指向一个对象的这种共享是不同的,因为这里a的修改并不会影响到b,它是有编译器完成的,有利于节省空间
如:令a=4,编译器会重新搜索栈中是否有4这个值,如果没有,则将4存进来,并令a指向4.a的改变不会影响b

5.4:本地方法栈内存——与调用的本地方法的语言相关,如果调用的是一个c语言方法则为一个c栈。本地方法可以回调java方法。若有java方法调用本地方法,虚拟机就运行这个本地方法。在虚拟机看来运行这个本地方法就是执行这个java方法,如果本地方法抛出异常,虚拟机就认为这个java方法抛出异常。
java通过java本地接口JNI(Java Native Interface)来调用其他语言编写的程序。在java里面用native修饰符来描述一个方法是本地方法

5.5:String的内存分配——String是一个特殊的包装类数据。可以用两种方法创建:
String str=new String("abc");//存放在堆中。每调用一次就会创建一个新的对象
String str = "abc"//先在栈中创建一个对String类的对象引用变量str,然后查找栈中有没有"abc"。如果没有则将"abc"存放进栈,并令str指向"abc"。如果已经有,则令str指向"abc"


第五章——数组和枚举

一:数组的声明和创建
1:声明——char s[];
2:创建—— s = new char[20];
3:初始化——s[0]='a';
简化方式——String names[] = {"a","b","c"};

4:数组的内存分配——数组一旦被创建,在内存里面占用连续的内存地址。数组的静态性:数组一旦被创建,就不能更改数组的长度
5:数组元素的访问:
更优化的for循环语句
for(int i=0; i<a.length; i++) ==》 for(int i : a)
 
二:数组的复制——数组一旦创建后,其大小不可调整。可以使用相同的引用变量来引用一个全新的数组:
int array[] = new int[6];==> array=new int[10];//第一个数组被有效地丢失,除非对它的其他引用保留在其他地方
java在system类中提供了一种特殊方法拷贝数组:arraycopy()
//原始数组
int myArray[] = {1,2,3,4,5,6};
//新数组,比原始数组大
int hold[] = {10,9,8,7,6,5,4,3,2,1};
//把原始数组的值拷贝到新的数组
System.arraycopy(myArray, 0, hold, 0, myArray.length);
//拷贝完成后,hold中有如下内容:1,2,3,4,5,6,4,3,2,1

注意——在处理对象数组时,arraycopy()拷贝的是引用,而不是对象。对象本身不改变。

三:数组的排序
1:基本排序方法
1.1:冒泡排序

 基本思路:对未排序的各元素从头到尾依次比较相邻的两个元素是否逆序(与欲排顺序相反),若逆序则交换这两个元素,经过第一轮比较排序后便可把最大(或最小)的元素排好,然后再用同样的方法把剩下的元素逐个比较,就得到所要的排序
如果有N个元素,则一共要进行N-1轮比较,第I轮要进行N-I次必经(如:有5个元素,则要进行5-1轮比较,第3轮则要进行5-3次比较)
View Code
public class BubbleSort {
    public static void main(String[] args){
        //需要排序的数组,目前是按照升序排列的
        int a[]=new int[5];
        a[0]=3;
        a[1]=4;
        a[2]=1;
        a[3]=5;
        a[4]=2;
        //冒泡排序
        for(int i=0; i<a.length; i++){
            for(int j=i+1; j<a.length; j++){
                //注意j的开始值是i+1,因为按照排序规则,比a[i]大的值都应该在它后面
                if(a[i] > a[j]){
                    int temp = a[j];
                    a[j]=a[i];
                    a[i]=temp;
                }
            }
        }
        for(int i : a){
            System.out.println("i="+i);
        }
    }
}

1.2:选择排序
基本思路:从所有元素中选择一个最小的元素a[i]放在a[0](即让最小元素a[i]与a[0]交换),作为第一轮;第二轮是从a[1]开始到最后的各个元素中选择一个最小元素,放入a[1]中;以此类推。n个数要进行(n-1)轮。比较次数和冒泡一样,但是在每一轮中只进行一次交换,比冒泡法的交换次数少,相对冒泡效率会高。

View Code
public class SelectSort {
    public static void main(String[] args){
        //需要排序的数组,目前是按照升序排列的
        int a[]=new int[5];
        a[0]=3;
        a[1]=4;
        a[2]=1;
        a[3]=5;
        a[4]=2;
        //选择法排序
        int temp;
        for(int i=0; i<a.length; i++){
            int lowIndex=i;
            //找出最小的一个索引
            for(int j=i+1; j<a.length; j++){
                if(a[j] < a[lowIndex]){
                    lowIndex = j;
                }
            }
            //交换
            temp=a[i];
            a[i]=a[lowIndex];
            a[lowIndex]=temp;
        }
        //输出
        for(int i : a){
            System.out.println("i="+i);
        }
    }
}

1.3:插入法排序
基本思路:每拿到一个元素,都要将这个元素与所有它之前的元素遍历比较一遍,让符合排序顺序的元素挨个移动到当前范围内它最应该出现的位置。
用前面的数组来举例:对一个有5个元素的数组进行升序排列,假设第一个元素的值被假定为已排好序了,那么我们将第2个元素与数组中的部分进行比较,如果第2个元素的值较小,则将它插入到第1个元素的前面,现在就由两个元素排好序了,我们再将没有排序的元素与排好序的元素列表进行比较,同样,如果小于第一个元素,就将它插入到第一个元素前面,但是如果大于第一个元素的话,我们就将它再与第2个元素的值进行比较,小于的话就排在第2个元素前面,大于的话就排在第2个元素的后面,以此类推,直到最后一个元素排完序

View Code
public class InsertSort {
    public static void main(String[] args){
        //需要排序的数组,目前是按照升序排列的
        int a[]=new int[5];
        a[0]=3;
        a[1]=4;
        a[2]=1;
        a[3]=5;
        a[4]=2;
        //插入法排序
        int temp;
        for(int i=1; i<a.length; i++){
            //i=1开始,因为第一个元素被认为是已经排好序了
            for(int j=i; (j>0) && (a[j]<a[j-1]); j--){
                //交换
                temp=a[j];
                a[j]=a[j-1];
                a[j-1]=temp;
            }
        }
        //输出
        for(int i : a){
            System.out.println("i="+i);
        }
    }
}

2:希尔(Shell)法排序
基本思路:先将数据按照固定的间隔分组,例如每隔4个分成一组,然后排序各分组的数据,形成以分组来看数据已经排序,从全部数据来看,较小值已经在前面,较大值已经在后面。将初步处理了的分组再用插入排序来排序。那么数据交换和移动的次数会减少。可以得到比插入排序法更高的效率

View Code
public class ShellSort {
    public static void main(String[] args){
        //需要排序的数组,目前是按照升序排列的
        int a[]=new int[5];
        a[0]=3;
        a[1]=4;
        a[2]=1;
        a[3]=5;
        a[4]=2;
        //shell法排序
        int j=0;
        int temp=0;
        //分组
        for(int increment=a.length/2; increment>0; increment/=2){
            //每个组内排序
            for(int i=increment; i<a.length; i++){
                temp=a[i];
                for(j=i; j>=increment; j-=increment){
                    if(temp < a[j-increment]){
                        a[j]=a[j-increment];
                    }else{
                        break;
                    }
                }
                a[j]=temp;
            }
        }
        //输出
        for(int i2 : a){
            System.out.println("i="+i2);
        }
    }
}

3:数组的排序——在java.util.Arrays类中有一个静态方法sort(升序)

四:数组实用类Arrays
1:public static <T> List<T> asList(T...a)
返回一个受指定数组支持的固定大小的列表。(对返回列表的更改会”直接写“到数组)此方法同Collection.toArray()一起,充当了基于数组的API与基于collection的API之间的桥梁。返回的列表是可序列化的,并且实现了RandomAccess
List<Integer> list=Arrays.asList(2,4,5,7,8,10,20);
for(int i=0; i<list.size(); i++){
    System.out.print(list.get(i)+",");
}
//输出:2,4,5,7,8,10,20

2:public statci boolean equals(数组1,数组2)——比较两个数组参数是否相同,如果是引用类型的数组,比较的是引用类型的equals方法。

3:public static void fill(数组,数据参数)——向数组种填充数据参数,把数组种所有元素的值设置为该数据。数组和数据参数类型必须一致或可以自动转化

4:public static void fill(数组,int fromIndex,int toIndex,数据参数)——向数组中指定的范围填充数据参数,此范围包括formIndex,但是不包括toIndex.数组和数据参数的类型必须一致,或可自动转化

5:public static int binarySearch(数组,数据参数)——查找数组种元素的值与给定数据相同的元素。数组和数据参数的类型必须一致,或可自动转化

6:public static void copyOf(数组,int newLength)——赋值指定的数组,截取下标0(包括)至newLength(不包括)范围
 
7:public static 数组 copyOfRange(数组,int from,int to)——将数组的指定范围复制到一个新数组。
 
8:public static String toString(数组)——返回指定数组内容的字符串表示形式
int[] arr={2,4,6,7,8,10};
System.out.print(Arrays.toString(arr));
//输出:[2,4,6,7,8,10]

五:枚举类型——类型安全、紧凑有效的枚举数值定义、运行的高效率

1:values()方法返回了一个由独立的StudentGrade实例构成的数组。valueOf(String):以字符串形式返回某一个具有枚举元素的值

public class Test{
    public enum StudentGrade{
        A,B,C,D,E,F
    };

    public static void main(String[] args){
        for(StudentGrade score : StudentGrade.values()){
            
        }
        
        StudentGrade score = StudentGrade.valueOf('A')
    }
}

 

第六章——常见类的使用
一:Object类——根类
1:equals方法(注意——覆盖equals方法应该连带覆盖hashCode方法)
2:hashCode方法——按照一定的算法得到的一个数值,是对象的散列吗值。主要用来再结合中实现快速查找等操作,也可以用于对象的比较。
java对hashCode的规定如下:
1)在同一个应用程序执行期间,对同一个对象调用hashCode(),必须返回相同的整数结果——前提是equals()所比较的信息都不曾被改动过。至于同一个应用程序在不同执行期所得的调用结果,无需一致
2)如果两个对象呗equals(Object)方法视为相等,那么对这两个对象调用hashCode必须获得相同的整数结果
3)如果两个对象被equals(Object)方法视为不相等,那么对这两个对象调用hashCode()不必产生不同的整数结果。应该注意到,对不同对象产生不同的整数结果,有可能提升hashTable(集合框架的一个类)的效率
简单的说——如果两个对象相同,那么它们的hashCode值一定要相同;如果两个对象的hashCode相同,它们并不一定相同
实现hashCode的方法:
1):对同一对象始终返回相同的hashcode,如下:
public int hashCode(){
  return 1;
}//合法,但是不好,因为每个对象具有相同的hashCode,会使得很多使用hashCode的类的运行效率大大降低,甚至发生错误
2):采用一定的算法来保证——现在eclipse自动生成equals方法和hashCode方法就是用这个算法
 
3:toString方法
 
二:String
1:length
2:equals  equalsIgnoreCase
3:public int compareTo(String s)——比较两个字符串大小。0:相等,大于0表示前面的字符串大于后面的,小于0反之(区分大小写)。compareToIgnoreCase:不区分。
同样还有equalsIgnoreCase
4:public boolean startsWith(String prefix)
startsWith(String prefix, int toffset)——测试此字符串从指定索引开始的子字符串是否以指定前缀开始
5:public boolean endsWith
6:public boolean regionMatches(int firstStart, String other, int otherStart, int length)测试两个字符串区域是否相等
 
三:字符检索
1:public char charAt(int index)
2:public int indexOf(int ch):返回指定字符ch在此字符串中第一次出现处的索引
3:public int indexOf(String str)返回第一次找到字符串str时的索引,如果没有找到,则返回-1
4:public int indexOf(int ch, int fromIndex)从指定的索引开始搜索,返回在此字符串中第一次出现指定字符处的索引,如有没有找到,返回-1
5:public int indexOf(String str, int fromIndex)从指定的索引开始搜索,返回在此字符串中第一次出现指定字符串处的索引,没有找到返回-1
6:public int lastIndexOf(String str)返回指定子字符串在此字符串中最右边出现处的索引。
 
四:截取字符
1:public String substring(int beginIndex)
2:Public string substring(int beginIndex, int endIndex)
 
五:替换
1:public String trim():截去最前面和最后面的空白符
2:public String replace(char oldChar, char newChar)
3:public String replaceAll(String regex, String replacement):使用给定的replacement替换此字符串中所有匹配给定的正则表达式的子字符串
4:toUpperCase()  toLowerCase()
 
六:字符串分解成数组
1:public byte[] getBytes():使用平台默认字符集将此String编码为byte序列,并将结果存储到一个新的byte数组种
2:public byte[] getBytes(Charset charset):使用给定的charset编码
public statci void main(String[] args)
{
    String str="欢迎Java哈哈";
    int charLen=str.length();
    int byteLen=str.getBytes().length;
    if(byteLen>charLen){
        int chineseNum=byteLen - charLen;
        System.out.println("str包含汉字, 汉字共" + chineseNum + "个");
    }  
    else
    {
          System.out.println("str没有包含汉字");
    }
}    

上例:判断一个字符串中是否有中文,并计算有几个汉字(结果:str包含汉字,汉字共6个)

 3:public void getChars(int srcBegin, intsrcEnd, char[] dst, int dstBegin)
拷贝字符串的部分字符序列到指定的字符数组的指定位置。要复制的第一个字符位于索引srcBegin处;
char[] arr={'1','2','3','4','5','6'};
String s="collection";
s.getChars(4,7,arr,2);
for(char c:arr){
    System.out.print(c+",");
}
//结果:1,2,e,c,t,6,

4:public char[] toCharArray();将字符串转换为一个新的字符数组
5:public String[] split(String regex)根据给定正则表达式拆分此字符串。
1)如果用".","|"作为分隔的话必须加“\\”,因为"."和"|"都是转义字符

七:展示字符串
1:public String concat(String str):拼接两个字符串,返回一个新字符串
2:public static String valueOf(参数列表):将参数的值转换成相应的字符串

八:Java中的正则表达式(javaj.util.regex)
1:public boolean matches(String regex):告知此字符是否匹配给定的正则表达式
2:java.util.regex.Pattern类:是正则表达式的编译表示形式,常见方法:
1)static Pattern compile(String expression)//expression:正则表达式
2)  static Pattern compile(String expression,int flags)//flags:
3:java.util.regex.Matcher类:通过解释Pattern对字符序列执行匹配操作的引擎
1)boolean matches():返回输入是否与模式匹配
2)boolean lookingAt():如有输入的起始匹配模式则返回True
3)boolean find()
4)  boolean find(int start):尝试查找下一个匹配,并在找到匹配时返回True

九:StringBuffer类和StringBuilder类
1:StringBuffer对象的内容是可以被修改的,不像String对象一旦创建,其内容是不能再被修改(read-only)。StringBuffer对象初始容量为16字符(缺省时)
StringBuffer buf = new StringBuffer(容量)//如果没有指定了容量,则默认16字符
StringBuffer buf = new StringBuffer(myString)//创建含有相应字符序列的StringBuffer对象,容量为myString.length()+16
常用方法:
1)length() 返回StringBuffer长度
2)capacity() 返回StringBuffer 容量
3)setLength(int newLength):增加或减小StringBuffer 的长度
4)charAt(int index):返回StringBuffer对象中指定位置的字符
5)  setCharAt(int index, char ch):设置StringBuffer对象中指定位置的字符
6)getChars(int srcBegin, int srcEnd, Char[] dst, int dstBegin):将StringBuffer对象中指定的字符子序列,拷贝到指定的字符数组dst
7)reverse():将StringBuffer对象中字符序列按逆序方式排列,可用作字符串倒序
8)append(..)
9)insert  允许将各种数组插到StringBuffer对象的指定位置
10)delete(int start, int end)和deleteCharAt(int index)

2:StringBuilder类——是一个可变的字符序列。此类提供一个与StringBuffer 兼容的API,但不保证同步。用作StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(普遍情况)。优先使用此类,其功能基本等同StringBuffer

十:Math类
1:ceil——向上取整;floor——向下取整; round——四舍五入
2:dbs——返回绝对值; min(double d1, double d2)——返回最小值;max()——返回最大值
public double random()——返回随机数

十一:日期操作类
1:Date类
1)public boolean after(Date when):测试此日期是否在指定日期之后
2)public boolean before(Date when)

2:DateFormat类和SimpleDateFormat类
Date对象表示时间的默认顺序是星期、月、日、小时、秒、年。DateFormat是个抽象类,SimpleDateFormat是它的子类
如:SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

常用方法:
public Date parse(String source):从给定字符串的开始解析文本,以生成一个日期
public String format(Date date):将一个Date格式化为日期/时间字符串

3:Calendar类——是一个抽象类。通过一个静态方法getInstance()来获取Calendar实例。
1)使用Calendar对日期进行部分析取:
public int get(int field):返回给定日历字段的值,如年份、月份、小时、星期等星期
2)使用Calendar进行日期运算:
public void add(int field, int amount)
Calendar c = Calendar.getInstance();
c.add(Calendar.DATE, 12);//当前日期加12天,如果是-12表示当前日期减去12天
3)为Calendar设置初始值
public void setTime(Date date):使用给定的Date设置此Calendar的当前时间
public void setTimeInMillis(long millis):用给定的long值设置此Calendar的当前时间值

十二:System类

1:命令行参数——当java程序启动时,可以添加0或多个命令行参数。不管使用双引号与否都作为字符串自动保存到main函数的参数中,参数之间用空格分隔。

2:系统属性——
1)System Properties是java提供的另外一种运行时给程序提供参数的方法。属性(Property)是名字和值之间的映射,这里名字和值都只能是String
2)java有一个类Properties描述了名字和值之间的映射。
System.getProperties方法返回系统的Properties对象
System.getProperty(String propertyName)方法返回对应名字属性的值
System.getProperty(String name, String value)重载方法当没有name指定的属性时,返回value指定的缺省值
3)每一个JVM都提供了一个组缺省属性,可以通过System.getProperties方法的帮助文档了解到。基本类型的包装类中包含静态方法,用于将属性值转换成对应类型的值。如
Boolean.getBoolean(String);如果属性不存在,返回false或null

3:控制台输入输出:
System.out;System.in;System.err

4:格式化输出printf

5:属性文件——后缀为.properties文件。基本格式key=value

读取properties文件:

try{
    String name="test.properties";
    InputStream in = new BufferedInputStream(new FileInputStream(name));
    Properties p = new Properties();
    p.load(in);

    System.out.println("test1的值==" + p.getProperty("test1"));
    System.out.println("test2的值==" + p.getProperty("test2"));
}
catch(Exception err){
    err.printStackTrace();
}    

 

第七章:抽象类和接口

一:抽象类

创建一个体现某些基本行为的类,并未该类声明方法,但不能再该类中实现该行为,而是在子类中实现该方法。抽象类不能直接使用,必须用子类去实现抽象类,然后使用其子类的实例。
然而可以创建一个变量,其类型是一个抽象类,并让它指向具体子类的一个实例,也就是可以使用抽象类来充当形参,实际实现类作为实参,也就是多态的应用
抽象类不一定包含抽象方法。但是包含抽象方法的类一定是抽象类。

二:接口——接口是特殊的抽象类

“面向接口编程”是面向对象世界的共识
接口(interface)也是一个类,在这个类中,所有的成员方法都是抽象的,也就是说他们都只有定义而没有具体实现,接口是抽象方法和常量值的定义的集合。从本质上说,接口是一种特殊的抽象类,用interface可以指定一个类必须做什么,而不是规定它如何去做

特性:
1:接口中声明的成员变量默认都是public static final的,必须显示的初始化。因此在常量声明时可以省略这些修饰符
2:接口中只能定义抽象方法,这些方法默认为public abstract的,因而在声明方法时可以省略这些修饰符。
试图在接口中定义实例变量、非抽象的实例方法以及静态方法,都是非法的

3:接口中没有构造方法,不能被实例化
4:一个接口不实现另外一个接口,但是可以继承多个其他接口。接口的多继承性弥补了雷的单继承

5:不同的程序模块通过接口相互访问。也就是:接口是各部分对外的统一外观。
接口在java程序设计中体现的思想就是隔离,因为接口只是描述一个统一的行为,所以开发人员在面向接口编程时并不关心具体的实现

三:接口作为类型使用

1:接口必须通过类来实现它的抽象方法,关键字:implements
2:如果一个类不能实现该接口的所有抽象方法,那么这个类必须被定义为抽象方法
3:不允许创建接口的实例,但允许定义接口类型的引用变量,该变量指向了实现改接口的类的实例
4:一个类只能继承一个父类,但可以实现多个接口

四:接口与抽象类的选择

相同点:

1:都代表类树形结构的抽象层。在使用引用变量时,尽量使用类结构的抽象层,使用方法的定义和实现分离,这样对代码有松散耦合的好处:
2:都不能被实例化
3:都能包含抽象方法。抽象方法用来描述系统提供哪些功能,而不必关心具体的实现

区别:

1:抽象类可以为部分方法提供实现,避免了在子类中重复实现这些方法,提高了代码的可重用性,这是抽象类的优势。而接口中只能包含抽象方法,不能包含任何实现
2:一个类只能继承一个直接的父类,但可以实现多个接口。这就是接口的优势

在接口和抽象类的选择上,必须遵守这样一个原则:
1:优先使用接口,尽量少用抽象类
2:选择抽象的时候通常是如下情况:需要定义子类的行为,又要为子类提供共性的功能

 

第八章:异常和断言

一:异常

1:异常是指当程序出错时创建的一种特殊的运行时错误对象。注意这个错误不是编译时的语法错误
在程序执行中,任何中断正常程序流程的异常条件就是错误或异常,如:
想打开的文件不存在;
网络连接中断
受控操作数超出预定范围
正在装载的类文件丢失

二:异常的处理

java 提供了一种异常处理模型。实现的是异常处理的抓抛模型。有两大优点
1):异常情况能仅在有必要之处加以处理,防止程序自动终止,而不在其发生处和需要进行处理处之间的每一级上均进行处理
2):能编写统一的,可重用的异常处理代码

2:try-catch块

3:finally块:无论是否出现异常,都会运行的块。通常finally块中可以编写资源返还给系统的语句,包括但不限于:
1)释放动态分配的内存块
2)关闭文件
3)关闭数据结果集
4)关闭与数据库建立的连接

4:throw语句——从代码中主动抛出异常,可以理解为一个向上抛出的动作。throw的操作数是任意一种异常类对象,是Throwable类类型或Throwable子类类型的一个对象。简单类型(如int)以及非Throwable类(如String或Object)不能用作异常

5:throws语句——用来在方法定义时声明异常
java中对异常的处理有两种方法,一个是try-catch块,自己处理;一个就是不做处理,向外throws,由调用该方法的代码去处理。

6:调用栈机制

如果方法中的一个语句抛出一个没有在相应的try/catch块中处理的异常,那么这个异常就被抛出到调用方法中。如果异常也没有在调用方法中被处理,它就被抛出到该方法的调用程序。这个过程要一直延续到异常被处理。如果异常没有被处理,就回到main(),而且main()不处理它,该异常就异常的中断程序。

在这种情况中main()调用另外一个方法,比如说first(),然后它调用另外一个方法如second()。如果在second()中发生异常,那么必须做一个检查来看看该异常是否有一个catch,如果没有,那么对调用栈(first())中的下一个方法进行检查,然后下一个(main)。如果这个异常在该调用栈上没有被最后一个方法处理的话,就会发生一个运行时错误,程序终止执行

三:异常的分类

1:错误(Error):JVM系统内部错误,资源耗尽等严重情况
2:异常(Exception 违例):其他因编程错误或偶然外因导致的一般性问题。如:对负数开平方根、空指针访问、试图读取不存在的文件,网络连接中断等
对于error,程序员根本无能为力

 异常分为运行时异常和受检查异常
运行时异常(RuntimeException)是指因设计或实现方式不当导致的问题,也就是说是程序员的原因导致的,本来可以避免的
除了运行时异常以及其子类,其他Exception及其子类都是受检查异常。这种异常要么用try-catch语句捕获它,否则编译不会通过

Java程序异常的处理原则:
1)对于Error和RuntimeException,可以在程序中进行捕获和处理,但不是必须的
2)对于其他异常,必须在程序中进行捕获和处理

预定义异常:这些异常的产生不需要程序员手动抛出,即不需要使用throw语句抛出异常,当产生异常时,系统会自动抛出

自定义异常——必须继承自Throwable类或其子类。以Exception结尾

 

四:断言

断言用于证明和测试程序的假设,比如“这个的值大于5”
断言可以在运行时从代码中完全删除,被代码运行速度没有影响

使用:
1:assert<<布尔表达式>>
2:assert<<布尔表达式>> : <<细节描述>>
如果布尔表达式的值为false,将抛出AssertionError异常;细节描述是AssertionError异常的描述文本
assert x == 10 : "Our assertion failed"

断言推荐使用方法:用于验证方法中的内部逻辑,包括:

内在不变式
控制流程不变式
后置条件和类不变式
注意:不推荐用于公有方法内的前置条件的检查

运行时屏蔽断言

java -disableassertions 或 java -da 类名

运行时允许断言

java -enableassertions 或 java -ea 类名

 

posted @ 2018-03-18 16:48  cateatmycode  阅读(336)  评论(0编辑  收藏  举报