主要内容摘自《Java7入门经典》
一、Java简介
1.1 Java的运行
1.2 JVM
- Java不是运行在本地机上,而是运行在Java 2 Platform的标准化环境中,该平台作为软件以Java运行环境(JRE)的形式在非常广泛的计算机的操作系统中得到了实现
- Java 2 Platform包含两部分───名为JVM的用软件实现的假想计算机和Java API
- Java API是一系列软件组件集合,提供编写完全成熟的交互式Java应用程序所需的工具
(个人理解:JDK>JRE>JVM,JRE里面包括JVM和Java API两大部分)
1.3 环境变量
- JAVA_HOME JDK安装目录
- PATH %JAVA_HOME%\bin;%JAVA_HOME%\jre\bin
- CLASSPATH .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar
2个路径:
- PATH:指定可执行文件的路径。当执行一个可执行文件时,如果不能在当前目录下找到,则依次在PATH中的路径寻找,如果仍找不到则报错
- CLASSPATH:指定Java编译或者运行时需要用到的类(.class)文件,可不配置
1.4 Unicode字符集
Unicode是一个标准字符集,用来支持对几乎所有的语言进行编码。Unicode使用16bit的编码来代表一个字符(即每个字符占2byte)
Java源代码是Unicode字符。注释、标识符以及字符和字符串都能使用Unicode集合中标识字母的任意字符。Java内部也支持使用Unicode来标识字符和字符串,所以框架支持一个程序中含有各国语言。最熟悉的ASCII集合对应Unicode集合的前128个字母。
超大字符集:32bit编码的超大字符集,用来标识由16bit字符定义基本多语言集合中没有包括的字符。
1.5 JDK常用包结构
java.lang 基础类,如:String,System
java.util 工具类,如:集合,随机数,日历
java.io 文件操作类,输入输出
java.net 网络操作
java.math 数学相关操作的类
java.sql 数据库操作
1.6 文档注释
Javadoc命令 Javadoc标记
--常用的文档注释
/**
*@BelongsProject:${PROJECT_NAME}
*@BelongsPackage:${PACKAGE_NAME}
*@Author: Dave
*@CreateTime: ${YEAR}-${MONTH}-${DAY} ${HOUR}:${MINUTE}
*@Desc:toto
*/
二、 程序、数据、变量和计算
2.1、变量
变量:内存的别名
字面量:显示的数据值
变量的命名规则:
- Java对大小写敏感
- 以大小写字母或下划线或$符开始,不能以数字开始
- 不能是关键字or字面量(包括为boolean类型的字面量true或false)
- 驼峰表示法
- 用大写字母定义标记为常量的变量,加关键字final
2.2、表达式
- 混合算数表达式:如果其中一个操作数为double类型,就在进行运算之前将另一个转换为double类型
- 显示转换 int a=1; (double)a
- 自动类型转换 小类型转换为大类型
2.3、数学函数和常量
Math类
abs(arg):绝对值
max(arg1,arg2) min(arg1,arg2)
sqrt(arg):平方根 cbrt(arg):立方根
pow(arg1,arg2):arg1的arg2次方
floor(arg):等同于参数or比参数小的最大整数值
ceil(arg):等同于参数or比参数大的最小整数值
2.4、枚举
enum Day{Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday}
枚举定义的最后没有分号。因为这里是定义一个类型,所以反括号的后面没有分号。
Day weekday=Day.Sunday;
三、循环与逻辑
3.1、决策
语句一般均具有决策功能
缩进:逻辑的视觉提示
3.2、逻辑运算符
& 逻辑与 && 条件与
| 逻辑或 || 条件或
^ 异或 !逻辑非
& 与 &&的区别:&&若左操作数为false,将不再计算右操作数的值
| 与 ||的区别: ||若左操作数为true,将不再计算右操作数的值
四、数组与字符串
Java对象:数组 字符串
4.1、数组
Java对象 同类型变量的集合
数组名+数组的索引(从数组首位置到该该元素的位移)
4.1.1 数组变量
数组变量与指向的数组是两个独立的实体,分配给数组变量的内存存储一个指向数组对象的引用,而不是存储数组本身。数组对象本身存储在另一处不同的内存实体中。
int[] primes; //待定义的整型数组的占位符
primes = new int[10];
指向对象的所有变量实际上存储了一些引用,其中记录它们所指向对象的内存地址
4.1.2 初始化数组
① int[] primes={1,2,3,4,5,6};
② int[] primes=new int[100];
primes[0]=2;
primes[1]=3;
③ double[] data=new double[10];
for(int i=0;i<10;i++){
data[i]=i+1;
}
4.1.3 二维数组
float[][] temperature =new temperature[10][365];
for(int i=0;i for(int j=0;j expression; } } float[][] samples; samples=new float[6][]; //samples变量现在引用一个含有6个元素的数组,其中每个元素都保存一个指向一维数组的引用。如果需要,也可以单独定义某个数组 samples[0]=new float[5]; samples[1]=new float[7]; long[][][] beans=new long[6][][]; beans[0]=new long[3][]; beans[1]=new long[4][]; beans[0][0]=new long[7]; beans[0][1]=new long[5]; char[] message=new char[50] char[] message={‘l’,’9’,’v’,’e’}; String str1="abc"; String[] names=new String[6]; String[] color={“red”,”yellow”,”black”,”green”,”blue”,”violent”}; 数组长度 primes.length //调用数据成员length 字符串长度 str.leng(); //调用函数方法 indexOf(char ch) indexOf(char ch,int index) indexOf(String str) indexOf(String str,int index) subString(index1, index2) split(“[]”,int):将字符串分割成标记并且将所有标记以String对象数组的方式返回 第一个参数:String对象,设定一个模式作为定义符。任何匹配该模式的定义符都被认为是一个标记的分隔符 第二个参数:是一个整数值,表示能应用该模式寻找标记的最大次数(影响找到的标记的最大数目)。若参数为0,则模式无次数限制,并且会丢弃所有的空标记,若参数为负数,模式次数同样没有限制,但是会保留并返回所有的空标记。(若有两个相邻的定义符,则会出现额外的标记) String str=”To be, or not to be”; String[] primes=str.split(“[, .]”,0); toCharArray():可以从String对象创建char类型的数组变量。由于toCharArray()创建char[]类型的数组并返回一个指向该数组的引用,因此只需要声明char[]类型的数组变量来保存数组引用即可-不需要为数组分配内存 getChars():将一个子字符串以字符数组的形式提取。但是这种情况下需要创建一个足够大的数组来保存这些字符并且将这个数组作为传递给getChars()方法的参数 getChars()方法的四个参数: 1)原字符串提取的第一个字符的索引位置(int) 2)原字符串提取的最后一个字符后面的索引位置(int) 3)用于目标数组的数组名(char[]) 4)用于保存目标数组的起始偏移量(int) example: String text=”To be or not to be”; char[] textArray=new char[3]; text.getChars(9,12,textArray,0); 使字符串执行基于集合的for循环 先将字符串转换为字符数组 for(int i:str.toCharArray()) String str=”To be or not to be”; byte[] textArray=text.getBytes(); char[] text={‘T’,’o’,’ ‘,’b’,’e’,’ ‘,’o’,’r’,’ ‘,’n’,’o’,’t’,’ ‘,’t’,’o’,’ ‘,’b’,’e’}; String str=text.copyValueOf(text); String str=new String(text); 类对象能直接修改,这两个类提供的操作没有区别,但是多线程能安全的使用StringBuffer对象。StringBuffer类操作已经被编码以避免因为两个或多个线程的并发访问而引起的错误(如并发的两个线程,一个读,一个写(改)),若确定可变长字符串只能使用单个线程访问时则考虑用StringBuilder类对象,因为StringBuilder类对象比StringBuffer类对象的操作更快。 StringBuffer strBuf=”A stitch in time”; //错误 初始化StringBuffer类对象必须使用new,StringBuffer类名以及括号之中的字符串字面量作为初始化值,不能像String那样只用String的字面量作为初始化值,这是因为StringBuffer对象不仅仅是它内部包含的字符串(缓冲区长度)。而字符串字面量按照定义就是String对象。 StringBuffer strBuf=new StringBuffer(“A stitch in time”); or: String str=”A stitch in time”; StringBuffer strBuf=new StringBuffer(“str1”); StringBuffer对象有一个被称为缓冲区的内存。StringBuffer对象中的字符串长度可以不同于该对象包含的缓冲区长度。缓冲区的长度被称为StringBuffer的容量。(长度是字符串的属性,相对的,容量是字符串缓冲区的属性) *为什么讨论StringBuffer的容量? StringBuffer对象的容量对存储和修改字符串的开销量影响巨大,故需要先合理分配足够的容量 *容量的变化规律? 可变长字符串的容量会随着字符串长度的增加自动增长,规律如下:默认容量为字符串长度加16(容量 n=str.length()+16),当字符串长度增加时(或通过函数修改了字符串的容量),若没超过原容量,则容量不会发生变化,若超过原容量长度,则容量变为2n+2,将该容量大小与新的字符串长度比较(或与修改的容量大小比较),二者中的较大值则为新的容量值(即容量为2n+2与newStr.length()中的较大值) *获得字符串的容量: int theCapacity = str.capacity() *修改字符串的容量值 str.ensureCapacity(40); setLength() 主要是用于减少字符串长度,末尾部分的字符串被丢弃,不影响容量。若增加字符串长度,则增加”\0000”字符。其容量变化同上。 将String和StringBuffer对象(或一部分)添加到StringBuffer中 StringBuffer strBuf=new StringBuffer(); strBuf.append(“Mary”).appen(“ hands”); or: StringBuffer strBuf=new StringBuffer(“A stitch in time”); String str=”a saves nine”; strBuf.append(str,2,12); append()附加的基本类型: Boolean char String Object int long float double Byte short char[] 注意:在StringBuffer对象中没有对应的getBytes()方法,但是可以通过调用StringBuffer对象的toString()方法获得一个String对象,然后对这个Sting对象调用getBytes()方法,进而获得与StringBuffer对象对应的byte[]数组。 strBuf.setCharAt(4,’Z’); //修改第五个字符为Z strBuf.delete(5,9); //删除第5个到第8个字符 strBuf.reverse(); //调到对象中字符的顺序 toString() 方法 实际上,编译器会大量 地联合使用toString与append()方法来实现String对象的串联。假定如下字符串: String str1=”Mary” String str2=” hands” String str3=” make” String str4=” light” String str5=” work” 当写下类似如下的语句时: String str=str1+str2+str3+str4+str5 编译器会实现如下内容: String str=new StringBuffer().append(str1).append(str2).append(str3).append(str4).append(str5).toString(); 预定义字符: 任意一个字符: 边界匹配器: 数量词: 分组: str.matches(regex) //字符串匹配正则表达式,等价于 Pattern.matches(regex,str) str.split(regex) //按某种正则表达式匹配规则分割字符串 replaceAll(regex,rep) //替换否和某种正则表达式规则的字符串 类可以很复杂,可以尽可能全面的包含某类对象的操作,如String类,几乎涵盖了在任何程序中可能进行的字符串操作。但通常只是定义一个适合特定应用程序的类。 对象 —— 实例 静态域:类变量。声明时使用static关键字,与类关联。由类的所有对象共享但并不属于任何特定对象,即使没有创建类对象,他们也存在。静态域的值被改变,那么新值会同步到所有对象中。 非静态域:实例变量。与每一个对象关联,每一个实例都拥有它自己的一个副本,能将同一个类下的特定对象与其它对象区分开。 静态方法:类方法。static声明,不能引用实例变量,Java编译器也不允许这样做 实例方法:与对象关联 静态成员:静态域 & 静态方法 实例成员:非静态域 & 非静态方法 静态成员:.运算符 double rootPi=Math.sqrt(Math.PI); 实例成员:与特定的对象有关(即只能使用对象调用实例变量和方法) 根据约定,Java中的类名要以大写字母开始 根据约定,值为常量的变量名称需要大写 方法:自包含的代码块,有一个名称,包含一些属性并且可以重用,同一个方法可以根据需求在程序的任意多个位置执行。 如果方法不返回值,可以调用关键字return来结束方法的执行,对于不返回值的方法来说,到达包括方法体的右花括号也等同于执行一条return语句。 参数:又称形参,有名称和类型,并且出现在方法定义的参数列表中。定义了调用方法时能够传递给方法的值的类型。 实参:在方法执行中传递给方法的值,而且参数值在方法执行过程中通过参数名引用。参数值得类型必须与方法定义中对应参数设定的类型一致。 局部变量:从声明位置开始到标识代码块结束的最近的右花括号为止,每次执行时都会重新创建这个变量,当方法执行完后,这个变量都会被销毁。局部变量不会被初始化,所以如果想要局部变量的初始值,就必须在声明它们时提供。 虽然传值机制对于参数类型都一样,但是它对对象的作用与基本类型的变量的作用并不相同,方法能修改作为参数传递的对象。因为类类型的变量包含的是指向对象的引用而不是对象本身,而指向该对象的引用的副本仍然指向同一个对象,所以方法中使用的参数名也指向作为参数传递的原始对象。将对象作为参数传递给方法时,应用的机制也可以理解为传址调用(pass-by-reference) 调用方法时避免任何替代参数的参数值被修改,编译器会检查以确保方法体中的代码不会尝试修改任何final参数 将方法的参数设置为final可以避免传给方法的对象引用被意外修改(即该对象引用不能指向另一个对象),但是无法避免修改对象本身。 实例方法能够访问类中的任意数据成员(可以使用类变量),类方法不能直接使用实例变量。对象(实例)可以调用静态方法或类变量。 ClassName(){ ...... } 处理销毁对象的过程成为垃圾回收,垃圾回收在Java中自动运行,但这并不意味着对象会从内存中直接消失。对象在程序中变得不可访问时,还需要一段时间才能消失,这不会影响程序的运行,仅仅意味着不能信任已销毁对象占有的内存会立即释放。这对于大多数情况而言没有影响,唯一可能影响的情形是涉及的对象非常大(比如达到几百万字节)或是需要不断的销毁和创建大量的对象,这时,可以试图调用定义在System类中的静态的gc()方法,鼓励JVM执行垃圾回收并释放这些对象占用的内存。这对JVM而言是尽力而为的任务,当gc()方法返回时,JVM会试图回收已舍弃的对象的内存,但不能保证全部恢复。也有可能因为调用gc()方法而使情况变的更糟:如垃圾回收正在执行一些恢复内存的准备,调用gc()会取消这种准备,导致速度变慢。 如果一个类中使用了toString()方法,并且这个类的一个对象被用作字符串连接运算+的一个操作数,那么toString()方法会将这个对象表示成一个字符串,必要时编译器会自动插入对toString()方法的调用。如假设thePoint是一个Point类型的对象,编写如下语句: System.out.println(“The point is at ”+thePoint); 编译器会自动调用toString()方法,将变量的thePoint引用的对象转换成一个字符串。 一般的,应该注意避免在对象之间创建隐式依赖。 隐式依赖: 只有当递归有明显优势时才使用它,因为递归方法会产生大量的负载。 包是一个唯一命名的类的集合 Java中的每个类都包含在一个包中,若没有定义,则隐式的使用默认包(default package)来保存类。而这并没有名称。 java.lang 包中的所有类在程序中总是可用 用于包中的类名不会妨碍另一个包或程序中的类名 对于类,同一个包中的类可以相互访问 对于类中的成员,访问属性如下所示 无访问属性 允许同一个包中的任意类的方法访问 public 只要声明为public,就允许任意位置的类方法访问 private 只允许内部的方法访问,完全不允许在类的外部访问 protect 允许同一个包中的任意类的方法访问并且允许任意位置的子类访问 可以将一个类的定义放到另一个类的定义中,这个内部类被称为嵌套类。如果需要,嵌套类也可以在其自身内部嵌套另一个类。包围嵌套类的外围类叫做顶级类。 定义嵌套类时,嵌套类与其它类成员一样将作为包围它的类的一个成员。可以与其它类成员一样设置嵌套类的访问属性,并且嵌套类在顶级类外部的可访问性也同样由访问属性决定 *example public class Outside{ …… public class Inside{ …… } …… } Outside outer=new Outside(); //没创建嵌套类对象 Outside.Inside inner=out.new Inside(); 基类/父类/超类——派生类(基类特殊化) 访问修饰符 访问属性 继承属性 public 在所有地方可用 完全继承 protected 同一个包中的类or不同包中的子类可以访问 只要类本身为public,就对继承没有限制 默认(无访问属性) 同一个包可以访问 阻止在不同包中的子类继承 Private 限制在一个类中 不能继承 同一个包中:不能继承private成员 不同的包中:不能继承private & 无访问属性 的成员(基类必须为public) 被隐藏的数据成员(同名即覆盖) 派生类中定义了某个与基类同名的数据成员,不管对应的类型或访问类型是否一样 与数据成员相似,private类型方法不能被继承,没有声明属性的方法,只有在同一个包中才能被继承。 构造函数不能被继承 在派生类中被继承的基类方法能访问所有的基类成员,包括没有被继承的成员(子类对象包含了原来基类对象的所有成员) 派生类中,与基类签名相同的方法(即名称和类型的顺序与数目相同) 派生类中的覆盖方法的访问属性可以与基类一样或者比基类更少一些,但是不能更多 派生类的构造函数对基类构造函数调用必须是派生类构造函数方法体中的第一条语句,如果派生类构造函数的第一条语句不是对基类构造函数的调用,编译器就会自动插入一条对基类默认构造函数(no—arg构造函数)的调用。 super(); 但是,这条自动插入的语句会导致编译错误。 因为基类中定义构造函数后,就不会再自动创建默认构造函数。 让编译器检查派生类中的方法的签名与超类中同名方法的签名是否相同 某给定类型的变量能引用不同类型的对象(不仅仅是引用给定类型的对象),并能自动调用该对象的方法——单个的方法调用会因为引用对象的不同而产生不同的行为 多态的必要条件: 1)对派生类对象起作用 派生类可以由任意直接或间接的基类类型的变量引用。 2)方法必须被声明基类(即正在使用的变量的类型的一个成员),并且必须被声明为所涉及对象所属类型的一个成员。在派生类中,这些方法的任何定义都必须与基类的签名一样,并且必须都有一个不含更多限制的修饰符 对于派生类中非基类成员的方法,不能使用基类类型的变量调用这些方法 派生类方法的返回类型必须与基类中对应方法的返回类型一样或是基类返回类型的子类,如果返回类型不同,但是派生类中方法的返回类型是基类返回类型的子类,那么返回类型被认为是协变的。 *当使用基类变量调用方法时,多态会根据引用的对象类型而不是变量的类型来选择要调用的方法 *基类变量引用的对象类型直到程序执行时才知道。因此,必须在程序运行时动态决定并选择要执行的方法——在编译时无法确定 *多态只应用于实例方法,不能应用于数据成员 public abstract Animal{ public abstract void Voice(); } 抽象类:由关键字abstract定义,这些方法没有定义并且不能被执行。其中声明了一种or多种方法,但是没有定义它们——因为实现这些方法没有任何意义。这些方法的方法体被省略掉。抽象方法的声明以分号结束。 abstract方法不能是private类型,因为private类型不能被继承从而重写 抽象类能引用类型,但是不能申明变量 Animal aAnimal=null; *当从一个抽象类派生另一个抽象方法时,并不需要在子类中实例化所有的方法。在这种情况下,子类是抽象的并且也不能实例化子类的任何对象 永远不要在类定义中设定Object类为基类——因为这会自动设定 Object类型的变量能存储指向任意类型对象的索引。(当要写一个方法来处理未知类型的对象时,非常有用) Object类的成员——会被所有的类继承(7个public方法,2个protected方法) 7个public方法: 注意:getClass(),notify(),notifyAll()和wait()都无法被覆盖——它们在Object类定义中被final关键字固定 2个protected方法: 假定一个Animal类型的变量pet,它可能包括一个指向Dog,Cat,Duck甚至Spaniel类型的对象的引用。为了弄清它实际指向的内容 1)可以编写如下语句: Class objectType=pet.getClass(); System.out.println(objectType.getName()); //Class类的一个成员,它返回Class 对象类的完全限定名称(com.dave.Dog) 亦可以 System.out.println(pet.getClass().getName()); 2)程序在执行时,Class类的一些实例表示程序中的每个类和接口。程序中的每个数组类型和每个基本类型都对应一个Class对象。当程序加载时,JVM会生成这些内容,因为Class主要由JVM使用,所以它没有构造函数。因此不能自行创建Class类型的对象。 在任何类、接口或基本类型的名称后附加.class就会获得对应的Class对象的引用。每个类型和接口都只有一个Class对象。 if(pet.getClass()=Duck.Class){ System.out.println(“By Goerge – it is a Duck”); } 3)instanceof():检验对象是否为所期望的类型 if(pet instanceof Duck){ Duck aDuck=(Duck)pet; aDuck.layEgg(); } public class TryVariableArgumentList { public static void main(String[] args) { printAll(2,"two",4,"four",5,"five",4.5,"four point five"); printAll(); printAll(25,"Anything goes",true,4E4,false); } public static void printAll(Object ... args){ for(Object arg:args){ System.out.print(arg+" "); } System.out.println(); } } 可以将可变类型参数列表限制为任意类类型或接口类型 public static void average(Double … args){ } 向上转换:①使用多态时执行方法,存储各种不同的基类对象并调用派生类的方法 ②将参数设定为基类类型以试用任何派生类型参数 向下转换:执行某个类特用的方法(向下转换需要显式转换) *对象必须是要转换的类的合法实例——要转换掉的类必须是对象的实际类型或是对象的超类。 将对象转换成超类时,Java会自动保留对象所属类型的实际类的所有信息。否则,就无法实现多态。因为关于对象的原始类型的信息已被保留,所以能够在层次结构中向下转换 *example public enum JacketSize { small(36),medium(40),large(42),extra_large(46),extra_extra_large(48); //构造函数,只能定义为private属性或不定义 JacketSize(int chestSize){ this.chestSize=chestSize; } public int chestSize(){ return chestSize; } @Override public String toString(){ switch(this){ case small:return "s"; case medium:return "M"; case large:return "L"; case extra_large:return "XL"; default: return "XXL"; } } private int chestSize; } 在类中实现接口:implements 接口的理解 interface A extends B,C{ } 接口中的方法:默认总是public和abstract访问属性,所以不用为它们设定——实际上,为它们设定任何访问属性都被认为是不好的编程习惯。决不能添加除默认属性(默认就是public和abstract)、public和abstract之外的任何属性——在接口中不能声明static方法。 接口中的常量:在接口中定义的常量被自动设置为public、final、static类型——对此没有选择。因为常量是final和static类型,所以必须为接口定义的常量提供初始化值(常量名按编程习惯最好大写)。当实用类实现接口时,在接口中定义的任何常量都会在类中直接使用。可以用与访问类中public和static域一样的方法来访问定义在接口中的常量——需要再常量的前面加上接口名称进行限定。 在实现接口的类中访问接口中的常量的方法 1)使用数据成员的限定名称从外部访问。 2)将类的静态成员导入到任何需要使用这些常量的类中,这允许常量通过非限定名称引用。(在这种情况下,MyClass类必须是有名称的包,因为import不能使用无名称的包) import static com.dave.Coversion.*; 接口中声明的方法 1)因为接口中的方法按照定义都是public类型,所以在自己的类中定义它们时都必须使用public,否则无法编译。 实现接口的类 1)如果两个或更多的接口声明了具有相同签名的方法(即名称和参数的类型与顺序都完全一样),而这些接口要在同一个类中得到实现。那么这个方法必须在声明他的所有接口中都返回相同的类型,如果不这样做,编译器就会报错。因为类中的方法必须有唯一的签名,而返回类型不是其中的一部分,在这个原则下,如果接口的返回类型不一样,那么在同一个类中就无法实现两个接口中的方法。 2)使用多个接口 public MyClass implements RemoteControl,AbsoluteControl{ } 如果某个类实现了多个接口,则每个接口类型的变量引用只能调用自己的方法,若要调用其它接口中的方法,则需将其转换为另一个接口类型。 AbsoluteControl ac=new MyClass(); ((RemoteControl)ac).remoteMethord(); 注:虽然RemoteControl接口和AbsoluteControl接口不相关,也能将ac的引用转化成RemoteControl类型。之所以能够完成,是因为ac引用的对象时MyClass类型,而MyClass恰好实现了这两个接口,所以也就合并了这两个接口类型。 *也可以将其转化为原始类型 (MyClass)ac 转化后的原始类型变量能调用所有接口的方法,但是无法获得多态行为。 对于任意类型的对象来说,只要对象所属的类实现了该接口,指向类对象的引用就可以作为参数传入相应的接口类型的参数中。 标准类库的方法通常都有接口类型的参数。String、StringBuffer、StringBuilder和CharBuffer都实现了CharSquence接口,而大量的类方法都有一个CharSquence类型的参数,在这种情况下,这些方法都能够使用上述任意类型的变量作为参数。StringBuffer和StringBuilder都有接口CharSquence类型的参数的构造函数,因此能够从实现了CharSquence接口的任意类型对象来创建这两个类类型的新对象。 在有些情况下,定义类只是为了在程序中定义一个对象,而且该对象的唯一用途就是作为方法的参数,在这种情况下,只要类扩展了一个已有的类或者实现了一个接口,就可以将其定义为匿名类。匿名类即不用为类提供名称 pickButton.addActionListener(new ActionListener(){ ...... }); Java中的异常是指当程序发生非正常情况时创建的一个对象,异常可以由JVM、标准类库的方法或应用程序代码创建,异常对象有一些域用来存储有关问题本质的一些信息。异常被称为抛出(throw),即标识意外情况的对象被作为参数传给一段特殊的、编写用来处理对应类型问题的程序代码。将异常对象作为参数接受称为捕获(catch)。 1)异常通常用来指示错误,它还能指示程序中值得关注的一些不寻常的事件 异常指示错误的好处:可以将处理错误的代码与正常执行的代码区分开来 2)异常的另一个积极面:提供了一种强制的对特定错误进行相应的方式。有很多种异常,它们必须在程序中包含对应的处理代码。否则,代码就不会被编译 3)处理异常涉及很多的处理负载。因此,并不是程序中所有的错误都需要被异常指示,异常应该保留给可能出现的或灾难性的情况。 异常总是标准类Throwable某个子类的对象。包括: 1)自己定义和抛出的异常 2)Java标准包中定义的标准异常 3)其它标准包中方法抛出的异常 1)Error:包括ThreadDeath、LinkageError、VisualMachineError等,属于不受检异常(unChecked Exception)。因为通过操作从这些类型的错误中进行恢复的可能性很小。希望做到的事(如果的确很幸运的话):读到由抛出的异常生成的错误消息,并且之后尝试找到导致异常问题的代码。 2)Excepiton:几乎所有的Exception类型的异常都是受检异常。所以如果代码可能导致它们被抛出,就必须在程序包中包括代码来处理它们,如果不这么做,程序不会编译。处理方法有两种: ①在方法内部处理异常 try-catch-finally代码块 ②声明抛出异常 throws try{ }catch(ArithmeticException e){ throw e; } 4.1.4 变长二维数组
4.1.5 变长的多维数组
4.1.6 字符数组
4.2、字符串
String str2="abc";
System.out.println(str1 == str2); //true
4.2.1 字符串数组
4.2.2字符串的操作
4.3、可变长字符串 StringBuffer StringBuilder
4.3.1 创建StringBuffer类对象
4.3.2 StringBuffer对象的容量
4.3.3 为StringBuffer修改字符串的长度
4.3.4 append()方法
4.3.4 可变长字符串的其它操作:charAt() getChars()
4.3.5 从StringBuffer对象中创建String对象
4.4 正则表达式
4.4.1 正则表达式
\\ 反斜线字符
. 任意一个字符
\d 任意一个数字字符[0-9]
\D 任意一个非数字字符
\w 任意一个字符[a-z0-9A-Z]
\W 非单词字符
\s 空白字符
\S 非空白字符
X 字符X
[abc] a、b、c中任意一个字符
[^abc] 除了a、b、c的任意字符
[a-zA-Z] a到z或A到Z的任意字符
[a-z&&[^m-p]] a到z且非m到p,等价于[a-lq-z]
^ 行的开头
$ 行的结尾
X? 0次或1次
X* 零次或多次
X+ 1次或多次
X{n} n次
X{n,} 至少n次
X{n,m} n次到m次之间
()4.4.2 字符串与正则表达式
五、定义类
5.1 类的理解
5.2 类定义中的域(静态域 & 实例域)
5.3 类定义中的方法(静态方法 & 实例方法)
5.4 访问成员和方法
5.5 定义类
5.6 定义方法
5.7 参数列表
5.8 将参数值传递给方法的过程
5.9 访问方法中的类数据成员
5.10 初始化代码块
5.11 构造函数(constructor)
5.12 对象
5.13 方法重载
5.14 使用对象
5.15 递归
5.16 包 (package)
5.17 类成员的访问控制(访问属性-access attribute)
5.18、嵌套类(nested class)
六、扩展类与继承
6.1 继承
6.1.1 继承数据成员
6.1.2 继承方法
6.1.3 派生类的构造函数
6.1.4 @Override
6.2 多态
6.3 抽象类
6.4 通用超类 Object
6.5 判断对象的类型
6.6 接受可变数目参数的方法 Object … args
6.7 转换对象
6.8 枚举进阶
6.9 接口 interface
2)接口中声明的方法所需的常量可在接口中一并声明,若在该接口的类中实现则显得有点笨拙。6.10 将接口类型作为参数使用
6.11 匿名类
七、异常
7.1 异常的基本概述
7.2 异常类型 Throwable的子类
7.3 try -catch –finally概述
7.4 定义自己的异常
7.5 throws与throw的理解