Java 的配置:
JAVA_HOME 指向JDK的安装目录(可以使用软连接)
PATH 要包含JDK的bin目录
CLASSPATH 可以简单的使用"."
一个Linux 实例:
JAVA_HOME=$HOME/java
PATH=$JAVA_HOME/bin:$PATH
CLASSPATH=.
export JAVA_HOME PATH CLASSPATH
使用source 测试profile 脚本
source .bash_profile
使用命令测试是否成功:
java -version (应该是1.5的)
mv
cd
经验是需要通过实践(训练)来获得!
编译Java源文件, 生成.class 字节码文件
工具:javac
javac -d 目标目录 filename.java
如: javac -d bin HelloWorld.java
这个命令把HelloWorld.java编译成.class
输出到bin文件夹中,在文件夹bin中还生成包
执行Java 类文件。
进入bin目录。执行:java day01.HelloWorld
包名.类名:全限定名
java 包名.类名
Java类的执行过程:Java会利用CLASSPATH搜索
类(全限定名),找到类对应的类文件,
加载并执行。
CLASSPATH是Java类的搜索路径
package day01;
public class HelloWorld{
public static void main(String[] args){
System.out.println("Hello World!");
}
}
编译: javac -d bin HelloWorld.java
运行: cd bin
java day01.HelloWorld
cd ..
export CLASSPATH=.:$HOME/sd1009/bin
java day01.HelloWorld
jar: Java发布包管理。
jar -cvf jarfile.jar package1 package2...
jar -xvf jarfile.jar
Java可以搜索CLASSPATH上配置的jar文件内容
打包实验
cd bin
jar -cf ../demo.jar day01
cd
export CLASSPATH=.:$HOME/sd1009/demo.jar
java day01.HelloWorld
解包实验,找到rt.jar, 释放开,找到里面的
String.class 文件,在包:java.lang中。
mkdir rt
cd rt
jar -xf $JAVA_HOME/jre/lib/rt.jar
cd java/lang
ls | String.class
Java 注释,是被Javac忽略的部分
经常用来为添加对代码的解释,提高软件的
可读性。还可以取消代码的功能。
1 多行注释 /* ... */
2 单行注释 //...
3 文档注释 /** ... */
可以使用javadoc导出java源代码中的文档注释
,生成Javadoc手册。(简单掌握)
javadoc -d doc String.java
二进制基础
192(10)-> 11000000(2)
128 64 32 16 8 4 2 1
1 1 0 0 0 0 0 0
计算机处理二进制:采用Byte为单位!
1Byte = 8bit
1(10) -> 00000001
16进制(0~9a~f)
41(16) -> 4*16^1 + 1*16^0 = 65(10)
0100 0001(2)=65(10)
4 1 (16)
16进制是二进制的简写形式!
数字式计算机只认识二进制数字!
16进制是为了方便人类简写二进制提供的
一种编码方案!
中(4e2d)
0100 1110 0010 1101
二进制补码
计算机内部只有二进制补码是数字!
正数的补码就是这个数本身
负数的补码是这个数取反加一
最高位是符号位,0表示正数,1表示负数
二进制补码 可以保证符号位参与运算,
并且保证结果是正确的。
byte:-65(10)-> bf(16)
65(10)-> 0100 0001(2)-> 41(16)
-65(10)-> -100 0001(2)->1011 1111(2)->bf(16)
-1(10)-> - 000 0001(2)->1111 1111(2)->ff
8位补码:
1111 1111(2补)-> - 000 0001(2)=-1
0111 1111 MAX 127 7f
1000 0000 MIN -128 80
16位补码表示
-1:ffff
MAX: 7fff;
MIN: 8000;
32位补码表示
-1:ffffffff
MAX: 7fffffff;
MIN: 80000000;
-97(10)-> - 110 0001(2)
-> 1001 1111(2补)
-> 9f(16)
96(10)->0110 0000(2)
96 01100000
-97 10011111
-----------------------------------
11111111
-97 10011111
X -1 11111111
------------------------------------
10011111
10011111
10011111
10011111
10011111
10011111
10011111
10011111
------------------------------------
01100001 -> 97
package day02;
public class BinDemo{
public static void main(String[] args){
int a = (byte)0xbf ;//1011 1111
System.out.println(a);//-65
}
}
运算符
数学运算符
1 封闭性:同种数据类型参与运算,
得到同种类型的结果
2 比int类型小的数据类型运算,
实际上是int类型运算。
3 常量运算是被Javac优化的运算,
相当于运算以后的字面量。
4 四则运算有溢出风险,
Java不对溢出进行检查
byte b = 5;
byte c = 6;
byte e = 5+6;//被Javac优化为11
//byte d = b+c;//错,实际上是int运算
//byte d = (byte)b+c;//错
byte d = (byte)(b+c); //对
System.out.println(e);
System.out.println(d);
int x = 1024*1024*1024*2;//上溢出
long l = 1024*1024*1024*2;//上溢
//long j = 1024*1024*1024*2*2L;//上溢
long j = 1024L*1024*1024*2*2;//正确
System.out.println(x);
System.out.println(l);
System.out.println(j);
int g = 3/2;//1,下溢出,舍掉余数,整除
double f = 3D/2;//1.5
% 求余数,取模运算
取余运算是周期函数
y=f(x)= x%5
x:0 1 2 3 4 5 6 7 8 9 10 11 12 ... n
y:0 1 2 3 4 0 1 2 3 4 0 1 2 ...
//逻辑运算
int age = 18;
char sex = '男';
boolean isChild = age<16;//false
boolean isMan = sex=='男';
boolean isBoy = isChild && isMan;
boolean isGirl = isChild && ! isMan;
boolean isChilden = isBoy || isGirl;
if(isBoy){
System.out.println("你好,小伙子!");
}
位运算
取反运算
int i = -1;
int j = ~i;//0
i = 0x7fffffff;
i = ~i;//0x80000000
按位与
1&1->1, 0&1->0, 0&1->0, 0&0->0
掩码运算
int mask = 0xf;// 0x0000000f
int c = '中'; // 0x00004e2d;
int l = c & mask;// 0x0000000d;
或运算
1|1-> 1, 0|1->1, 0|1->1, 0|0->0
把中国两个字拼成一个int数据
再拆开
int c1 = 0x4e2d0000;// 0x4e2d0000
int c2 = '国';// 0x0000xxxx
int c3 = c1 | c2;// 0x4e2dxxxx
int mask = 0x0000ffff;
char cx = (char)(c3 & mask);
移位
>> 有符号移位,相当于数学除法,
高位:正数补0,负数补1,保证符号位不变
如: -2 >> 1 结果是 -1,相当于数学 -2/2
-2:11111111 11111111 11111111 11111110
-2 移位以后,高位补1:
-1:111111111 11111111 11111111 1111111
<< 数学乘法 每次乘2
给定n 产生n位的掩码
n=4;
mask = ~(-1<<n);
>>> 无符号右移, 高位永远补0
比较如下表达式:
-1>>>1 -> 0x8fffffff,
-1>>1 -> 0xffffffff,
1>>1 -> 0x00000000
++, --
先++(++a):先将a加1,然后a的值作为整个
表达式的值。
后++(a++):先将a的值作为整个表达式的值
然后再将a加1。
int a = 1;
int b = a++;
int c = ++a;
a=a++;
a=++a;
int i = 0;
int x = i++%5;
x = i++%5;
x = i++%5;
x = i++%5;
x = i++%5;
x = i++%5;
x = i++%5;
x = i++%5;
x = i++%5;
条件运算符: ? :
String msg = isBoy ? "小伙子" : "小姑娘";
计算查询结果显示页数的实例:
int rows = 31;//查询结果数量
int size = 15;//每页数量
int pages =
rows%size==0 ? rows/size : rows/size+1;
运算符的优先级
运算符的结合型
int a = b+c+d;
int a = b = c = 1;
int a=3;
int b = 2 + (a+=5);
作业:
1 把ABCD字符拼成一个int类型数据
然后再拆开
2 实现华氏度到摄氏度的转换:
提示:
Scanner console =
new Scanner(System.in);
int val = console.nextInt(); //读取温度
String t = console.next(); //读取温度类型
char c = t.charAt(0);//获得温度类型的字符
if(c == 'f'){//比较稳定类型
}
double d = 1.78;
int x = (int)(d+0.5)//四舍五入
选择流程控制
1 尽量减少使用否定条件作为条件表达式
2 尽量减少使用else
3 尽量减少嵌套使用!
判断某一天是否有航班(if 位运算)
3
byte 00010101
byte 00001000
for循环
练习:
从控制台读取数字字符串,转换为整数
如:"23765" -> 23765
提示:
for(int i=0; i<str.length(); i++){
//每个字符
char c = str.charAt(i);
int n = c - '0';
sum = sum*10 + n;
}
while循环
实例:
输出一个整数的二进制字符串
如:0x15 -> "10101"
提示:
int a = console.nextInt();
int mask = 1;
String s = "";
int last = a & mask;
s = last + s;
a>>>=1; //a = a>>>1;
last = a & mask;
s = last + s;
a>>>=1;
last = a & mask;
s = last + s;
a>>>=1;
//a==0 结束
//...
do ... while 循环
实例:
整数转十六进制字符串
如:20013 -> 4e2d
提示:
do{
last>9
last -> 'a'~'f'; 'a' + (last-10)
}while(num != 0);
调试:
1 利用输出语句输出软件的状态(数据)
2 运行软件,把输出的状态和理想数据比较
找出问题所在。
void listFiles(String path){
//循环当前目录内容{
//如果当前项目是目录
// 再列出这个目录内容listFiles(目录)
//}
}
数组:
int score1 = console.nextInt();
int score2 = console.nextInt();
int score3 = console.nextInt();
int score4 = console.nextInt();
int score5 = console.nextInt();
//...
int[] score = new int[100];
for(int i=0; i<score.length; i++){
score[i]=console.nextInt();
}
1 数组长度固定,元素类型相同
2 数组声明:
int[] ary;//推荐使用
int ary[];//不建议使用!符合C程序员的习惯
3 初始化:
int[] ary = {1,3,3,'1'};//{}静态初始化
直接使用{} 只能在初始化时候使用,
不能作为赋值语句出现
int[] ary = new int[]{1,2,4};//动态初始化
//ary = {2,4}; //错,{}不能作为赋值语句
ary = new int[]{2,4};//对
数组初始化必须明确长度!
int[] ary = new ary[100];
//int[] ary = new ary[];//错误
int[] ary = {};//对,0长度
int[] ary = new int[0];//对,0长度
数组元素默认自动初始化,初始化为“零”值
“零”值:
int, long, byte, short, float, double->0
char -> '\u0000' ==0
boolean -> false
引用类型 -> null
int[] ary = new ary[10];
System.out.println(ary[3]);//0 //对
int[] ary = new ary[4];
ary[3]=1;
ary[2]=2;
//ary[4]=5; //错误,运行时候,越界
int[] a2 = ary;
System.out.println(a2[0]);
4 如果访问超过数组下标范围,
运行时会出现数组越界错误
5 数组变量的赋值,是引用地址的复制,
赋值结果是两个变量引用同一数组对象实例
int[] a2 = ary;
6 如果需要复制一个数组实例,需要如下
int[] ary = {1,2,4,5};
int[] ary1 = new int[ary.length];
for(int i=0; i<ary.length; i++){
ary1[i] = ary[i];
}
ary1 就是 ary的副本了!
Java 提供了数组复制到方法System.arraycopy();
int[] ary = {1,2,4,5};
int[] ary1 = new int[ary.length];
System.arraycopy(ary, 0, ary1, 0, ary.length);
二维数组
初始化:
int[][] ary = new int[2][3];
int[] ary1 = ary[0];
静态初始化
int[][] ary = {{1,2},{3,4,5},{4,5,6,8}};
初始化同时指定元素
int[][] ary = new int[][]{{1,2},{3,4,5},{4,5,6,8}};
只指定第一维的长度
int[][] ary = new int[2][];
ary[0] = new int[5];
ary[1] = new int[2];
数组实例:
1 EAN-13码的检查码的算法 ,例如假设一EAN-13码各码代号如下:
N1 N2 N3 N4 N5 N6 N7 N8 N9 N10 N11 N12 C
检查码之计算步骤如下:
C1 = N1+ N3+N5+N7+N9+N11
C2 = (N2+N4+N6+N8+N10+N12)× 3
CC = (C1+C2) 取个位数
C (检查码) = 10 - CC (若值为10,则取0)
2 身份证第18位计算法
身份证第18位(校验码)的计算方法
1、将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2。
2、将这17位数字和系数相乘的结果相加。
3、用加出来和除以11,看余数是多少?
4、余数只可能有0-1-2-3-4-5-6-7-8-9-10这11个数字。其分别对应的最后一位身份证的号码为1-0-X-9-8-7-6-5-4-3-2。
5、通过上面得知如果余数是2,就会在身份证的第18位数字上出现罗马数字的Ⅹ。如果余数是10,身份证的最后一位号码就是2。
例如:某男性的身份证号码是34052419800101001X。我们要看看这个身份证是不是合法的身份证。
首先我们得出前17位的乘积和是189,然后用189除以11得出的结果是17+2/11,也就是说其余数是2。最后通过对应规则就可以知道余数2对应的数字是x。所以,可以判定这是一个合格的身份证号码。
3 实现文字的竖排
排序:
1 选择排序:通过n-1轮比较,每轮找到一个最小的放到前面。
2 冒泡排序:每次比较相邻的元素,如果前一个大交换,每轮比较会把最大的交换到最后,完成一个最大的排序。经过n-1轮比较排序完毕。冒泡就是比喻每次有一个大数飘到最后。
插入式排序:把后半部的每个元素插入到前
半部已经排序的序列中。
eclipse:日食、月食
www.eclipse.org
Eclipse 是用Java开发。不是纯Java开发
图形界面使用SWT 包含一定的C代码,不是绝对
的跨平台的。
SWT 提供了几乎全部的主流平台的支持
Eclipse可以在所有主流平台(OS)上运行
下载要注意平台(OS)版本
下载:Java 开发版本。
Eclipse就是一个压缩包。释放就可以
Linux 安装实例:
tar -xzf /opt/eclipse-SDK-3.2.2-linux-gtk.tar.gz
./eclipse/eclipse
Eclipse 中的概念:
workspace: 一个项目默认保存目录
默认: /home/soft01/workspace
Project: 代表一个软件工程
类:逻辑上用来描述具体实体概念的。
如:图书馆中的书,一卡通
具体概念(类)是一个系统所管理的事务的抽象。
具体概念的实例叫:对象。
引用(变量):用来操作对象的句柄。
构造器:描述创建一个对象的过程。
构造器的参数,是创建一个对象依赖的条件
默认构造器:如果类没有声明任何构造器
Javac 默认提供一个无参数构造器,反之
如果声明了任何的构造器,Javac将不再提供。
Java 调用方法,一定的存在。Java根据“方法
签名” 识别调用方法
方法签名: 方法名称和参数列表。
方法的重载:方法名相同,方法参数不同(参数
类型,参数顺序,和参数名称无关!)
构造器可以重载,经常重载
不能在空(null)引用上访问属性和方法
否则的话会出现空指针异常。
Debug 提示: 找在那个引用
调用了方法或者属性,研究这个引用在哪里
赋值的对象!
一个Java源文件只能有一个共有类,文件名必须和公有类名一致
1 一个Java文件可以有多个类
2 如果没有公有类文件名和任意类名一致
3 建议一个文件一个类,并且都是公有类
文件中的关键字顺序:
1 有包的话,必须在首行
2 import 有的话必须在package之后
3 class 在 import之后
4 方法要声明在类中。
5 语句要写在方法中。
6 类中可以声明变量,但是不是语句!
this 的用法:
1 引用当前对象本身
2 this() 调用当前类的其他构造器,根据参数类型选择,
合适的构造器。经常用来进行重载构造器代码的重用。
this()必须写在构造器的第一行!
访问修饰:
默认修饰: 类内部和同包内部可以访问,包外部不可见。
私有的: 只在类的内部可以访问。
公有的:在任何地方都可以访问。
保护的:在子类和同包中可以访问
1 习惯上属性,方法,尽可能私有的。
2 提供适当是属性访问方法(getXXX, setXXX)
XXX 被称为Java Bean属性
3 建议一个文件一个类,并且都是公有类
4 在继承中为了子类准备的资源,使用保护的修饰。
关于Java Bean:
1 是一个普通的Java类, 但是要符合一些语法约定
2 需要有package
3 需要有无参数构造器
4 需要实现序列化接口(在IO中仔细学习)
5 可以包含由getXxx 和 setXxx 说明的Bean属性
boolean Bean属性 的getXxx 可以是 isXxx
Bean属性的名称: xxx
6 JavaBean 有时候也被称为POJO(老Java对象)
继承: 语法: class A extends B
1 A类是B类的扩展,其中A叫子类,B叫父类。
2 子类继承父类的特征和行为。
3 语义上表达A是B的字类型,就是:A是一种B
如: 蟑螂是昆虫
4 Java只允许单继承
只有一个父类
父类有多个子类
5 如果类没有继承任何类,默认继承于Object
继承中的实例构造
1 构造器是不能继承的!
2 子类构造器默认递归调用父类无参数构造器。
3 创建子类实例默认先递归分配父类空间
4 子类实例默认是父类型的实例
5 如果父类没有无参数构造器,必须显示的调用
父类有参数构造器,使用super() 调用父类构造器
6 为了减少麻烦,建议所有类都提供无参数构造器。
7 super() 必须写在构造器第一行,和this()互斥
在构造器的第一行默认存在super();
super:
1 调用父类的构造器: super()
2 明确访问当前实例父类中的声明属性或方法: super.name
super.isRuning();
属性 <=> 字段(Field)
覆盖(重写)Override:
1 子类修改父类的行为
2 子类提供一个与父类一样方法签名的方法
Object(东西)对象
继承中多态现象: 父类型引用子类实例, 会出现多态现象
重载和覆盖会造成行为的多态。
如:问题有多种实例,可能是单选或者多选
汽车是有多种的。
引用类型转换:
1 父类型可以引用子类型实例。子类型实例一定是父类型实例。
2 子类型的引用可以赋值给父类型引用,发生自动类型转换
3 反之需要强制类型转换,如果不成功,会抛出异常。
4 小到大自动完成,大到小需要强制类型转换
5 类型转换也叫“造型”
属性静态绑定(声明时候确定),方法动态绑定(覆盖的结果)
以上现象造成同一个对象上
1 同名属性值会出现不同的结果
2 方法的调用都是同一个结果。
解决方案:
1 习惯上子类尽量不定义与父类相同的属性。
2 属性尽量私有,使用属性访问方法存取属性。
总之:按照JavaBean习惯定义任何一个类!
动态:在运行期分配的资源都是动态的:如对象的属性和方法。
静态:是指在对象创建之前存在的属性,方法,是属于全体类的。
static 静态修饰
1 可以修饰变量,表示属于类的属性,全体实例共享一份静态
变量。
2 静态变量可以使用类名访问。
3 静态变量可以修饰方法,表示属于类的方法。
4 静态方法可以使用类名访问。静态方法属于类全体的公共
方法,一般都是不依赖对象工具方法。
5 静态方法只能访问静态资源(属性和方法)
6 静态代码块,在类的加载后执行, 可以用来初始化一些
配置信息,应用的不是非常广泛的。
静态属性实例:Math.PI, Math.E, Integer.MAX_VALUE
静态方法实例:Math.sqrt() Integet.parseInt()
类的加载:
1 在第一次使用时候加载,按需加载。
2 类加载以后分配类的静态变量。
3 加载以后立即执行静态代码块。
final (最终的)
1 final修饰属性,不能修改!
2 final修饰的局部变量/方法型参数 只能初始化
3 final修饰类,类不能再继承
4 final修饰方法,方法不能再被覆盖(写出测试代码)
5 强烈不建议使用 3,4 !
关于常量:
1 Java中没有真正的语言意义的常量
2 使用static final 声明的成员变量,代表常量。
3 习惯上 ”static final 声明的是常量“
abstract 抽象
1 abstract 修饰抽象方法,抽象方法不能有方法体
2 包含抽象方法的类,一定是抽象类,使用 abstract修饰
3 抽象类不能直接实例化,使用抽象概念可以声明引用变量,
抽象概念的引用变量可以引用具体的子类实例。
4 抽象类只能被继承,子类需要实现抽象类的抽象方法。
接口(interface)
1 所有方法都是抽象的类可以声明成接口。
2 接口表达是纯抽象的概念。
3 接口中声明的变量只能是常量。默认就是常量(static final)。
4 接口中的方法默认都是公有抽象的(public abstract)
5 接口不能实例化,只能被实现
6 实现一个接口,必须实现所有方法。
7 如果不全部实现,这个类一定是抽象类。
8 接口可以定义变量,可以引用实现类的实例
9 接口相当于实现类的父类型!
10 接口之间可以继承,一定是概念的具体化
11 类可以实现多个接口,实现多继承,表达:也是概念
在商业软件中,实体概念之间不推荐使用继承。
在软件的体系结构中会大量的使用接口,抽象类,继承,实现
等“继承关系” 维护一个可以扩展到架构。
关于接口:
1 接口的是约定
系统分析员定义了接口,程序员实现接口,要实现接口
所有的方法,这样分析员就通过接口约束了程序员的实现!
接口就是分析员与程序员之间的约定!
OOA/OOD -> OOP
2 接口也是标准
JDBC、JSP/Servlet, DOM ...
关于equals
1 默认是==比较,
2 建议覆盖equals,根据对象内容(属性)进行比较
自反性:对于任何非空引用值 x,x.equals(x)
都应返回 true。
对称性:对于任何非空引用值 x 和 y,
当且仅当 y.equals(x) 返回 true 时,
x.equals(y) 才应返回 true。
传递性:对于任何非空引用值 x、y 和 z,
如果 x.equals(y) 返回 true,并且 y.equals(z)
返回 true,那么 x.equals(z) 应返回 true。
一致性:对于任何非空引用值 x 和 y,多次调用
x.equals(y) 始终返回 true 或始终返回 false,
前提是对象上 equals 比较中所用的信息没有被修改。
对于任何非空引用值 x,x.equals(null)
都应返回 false。
方法:hashCode()
1 如果覆盖了equals方法,就必须一同覆盖hashCode()
2 如果两个对象 equals 比较为true,他们的hashCode返回
结果必须一样
3 如果两个对象 equals 比较为false,他们的hashCode返回
结果必须不一样
4 值是一个整数。
5 一个对象创建以后,hashCode() 结果要稳定不变!
6 在Object中默认的hashCode的值是与堆对象地址对应的一
个整数
JDK 类库中的类,一般都覆盖了equals() 和 hashCode()
如:String 覆盖了equals, 两个相同内容的String,
hashCode() 一定一样。
toString() 方法
1 返回当前对象的"文本描述",按照“习惯”书写. 如:方块A,(x,y)
2 默认的输出语句和字符串连接会调用toString() 方法,作为结果
3 Object 默认的toString() 的值是:
全限定名@hashCode
4 Java建议覆盖toString() 提供合理是值。
5 Java的类库基本都覆盖了toString().
0~n 对应X的运算可以采用数组完成:
//char[] c = {'0', '1', '2'... 'f'};
//char[] ch = {'零','壹', ... , '玖'};
//char[] cx = {'元','拾','佰'... , '玖'};
//String[] rankName =
{"2", "3","4", "5", "6", "7", "8", "9"
, "10", "J", "Q", "K", "A"};
clone() 克隆方法, 就是复制
1 需要覆盖父类提供的clone方法,要开放为公共的。
2 Object 提供的clone方法 是保护方法,默认不能公共调用
3 覆盖时候经常把异常处理掉
4 如果需要使用父类的clone()方法,必须实现Clonable接口
5 Object 提供的clone() 方法是浅层复制。
6 object克隆提供对象的浅层复制,
7 * java 系统提供的复制, 基本都是浅层复制
8 clone方法不是经常被覆盖!
finalize() 方法
1 和垃圾收集器有关。
2 finalize()在对象销毁之前由垃圾收集器调用。
3 可以被覆盖,但是不推荐覆盖
4 如果要覆盖,必须在代码中调用super.finalize()
5 Object .finalize() 方法会执行一些重要的内存回收操作
6 垃圾回收:一个对象不被任何引用所引用的时候。这个对象就是
内存垃圾,垃圾回收器会在系统空闲,或者特定时机(可以配置)
7 垃圾回收可以通过JVM的配置进行优化。
8 System.gc() 可以让JVM 尽快启动 GC(垃圾回收器)
9 不推荐在finalize() 里面写一些逻辑,执行不是很可靠
String 类,StringBuffer(旧),StringBuilder(新)
1 关于静态String,一般情况下相同内容的静态String(字面量)
是同一个对象。
2 大多数字符串运算返回的都是新String 实例
3 静态String 是指静态字面量,动态字符串是指运行期分配的String
4 String 使用“不变模式” 设计,字符串对象一旦创建了,
内容永远不变!字符串对象不变,不是引用不可改变。
引用值不变使用final 修饰
5 因为String是不变模式,所以String的方法返回都是新对象
(除了toString())
关于“不变模式”
1 保证任何情况下对象一旦创建,对象的属性就再也不能修改了
通过语法来约束实现。
使用第三方的API
1 获取API,并且释放到一个目录下
2 把API的类库(.jar 文件)配置到CLASSPATH
在eclipse: Project(右键)->Properties->
Java Buide Path->Libraries->Add Jar
3 查看API手册
4 根据手册,导入到代码中使用
字符的编码
关于编码方案:
1 ASCII 128个英文+符号, 后来扩展到256字符,如:A->65
2 IS0_8859-1 就是 ASCII, 如:A:41
3 GB2312中文编码(6000+汉字),是变长编码(1~2Btye)
其中1Byte时候和ASCII兼容,没有:玥,喆,镕,焗
常用艺术的字库都是(GB2312)的, 如:中:d6d0 A:41
4 GBK扩展了GB2312标准(兼容),1~2Byte编码,定义了
20000+汉字,几乎包括所有汉字,包括全部的CJK
WIN XP 中文采用是GBK,如:中:d6d0 A:41
5 UNICODE 是国际化组织 全球范围内文字,和ASC兼容
超过80000,包括CJK。Unicode 定义了多种编码方案
UTF-16BE, 采用16位定长编码,任何文字都一样。
能够表示 65535字
如:A= 0041 中: 4e2d
UTF-8, 采用:1~4Byte 的变长编码,表示全部的80000+字
英文采用,1Byte编码,与AscII一致,中文是3个Byte
如:A:41, 中:e4 b8 ad
1 Java的字符串内部编码Unicode(UTF-16BE),
Java 经常需要将GBK->UTF-16BE, 一般情况下Java会默认支持
本地编码到Java内码的转换
如: byte[] gbk = {(byte)d6,(byte)d0,41,42};
String str = new String(gbk);
正则表达式:
字符
x 字符 x
\\ 反斜线字符
\0n 带有八进制值 0 的字符 n (0 <= n <= 7)
\0nn 带有八进制值 0 的字符 nn (0 <= n <= 7)
\0mnn 带有八进制值 0 的字符 mnn(0 <= m <= 3、0 <= n <= 7)
\xhh 带有十六进制值 0x 的字符 hh
\uhhhh 带有十六进制值 0x 的字符 hhhh
\t 制表符 ('\u0009')
\n 新行(换行)符 ('\u000A')
\r 回车符 ('\u000D')
\f 换页符 ('\u000C')
\a 报警 (bell) 符 ('\u0007')
\e 转义符 ('\u001B')
\cx 对应于 x 的控制符
字符类
[abc] a、b 或 c(简单类)
[^abc] 任何字符,除了 a、b 或 c(否定)
[a-zA-Z] a 到 z 或 A 到 Z,两头的字母包括在内(范围)
[a-d[m-p]] a 到 d 或 m 到 p:[a-dm-p](并集)
[a-z&&[def]] d、e 或 f(交集)
[a-z&&[^bc]] a 到 z,除了 b 和 c:[ad-z](减去)
[a-z&&[^m-p]] a 到 z,而非 m 到 p:[a-lq-z](减去)
预定义字符类
. 任何字符(与行结束符可能匹配也可能不匹配)
\d 数字:[0-9]
\D 非数字: [^0-9]
\s 空白字符:[ \t\n\x0B\f\r]
\S 非空白字符:[^\s]
\w 单词字符:[a-zA-Z_0-9]
\W 非单词字符:[^\w]
POSIX 字符类(仅 US-ASCII)
\p{Lower} 小写字母字符:[a-z]
\p{Upper} 大写字母字符:[A-Z]
\p{ASCII} 所有 ASCII:[\x00-\x7F]
\p{Alpha} 字母字符:[\p{Lower}\p{Upper}]
\p{Digit} 十进制数字:[0-9]
\p{Alnum} 字母数字字符:[\p{Alpha}\p{Digit}]
\p{Punct} 标点符号:!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
\p{Graph} 可见字符:[\p{Alnum}\p{Punct}]
\p{Print} 可打印字符:[\p{Graph}\x20]
\p{Blank} 空格或制表符:[ \t]
\p{Cntrl} 控制字符:[\x00-\x1F\x7F]
\p{XDigit} 十六进制数字:[0-9a-fA-F]
\p{Space} 空白字符:[ \t\n\x0B\f\r]
java.lang.Character 类(简单的 java 字符类型)
\p{javaLowerCase} 等效于 java.lang.Character.isLowerCase()
\p{javaUpperCase} 等效于 java.lang.Character.isUpperCase()
\p{javaWhitespace} 等效于 java.lang.Character.isWhitespace()
\p{javaMirrored} 等效于 java.lang.Character.isMirrored()
Unicode 块和类别的类
\p{InGreek} Greek 块(简单块)中的字符
\p{Lu} 大写字母(简单类别)
\p{Sc} 货币符号
\P{InGreek} 所有字符,Greek 块中的除外(否定)
[\p{L}&&[^\p{Lu}]] 所有字母,大写字母除外(减去)
边界匹配器
^ 行的开头
$ 行的结尾
\b 单词边界
\B 非单词边界
\A 输入的开头
\G 上一个匹配的结尾
\Z 输入的结尾,仅用于最后的结束符(如果有的话)
\z 输入的结尾
Greedy 数量词
X? X,一次或一次也没有
X* X,零次或多次
X+ X,一次或多次
X{n} X,恰好 n 次
X{n,} X,至少 n 次
X{n,m} X,至少 n 次,但是不超过 m 次
Reluctant 数量词
X?? X,一次或一次也没有
X*? X,零次或多次
X+? X,一次或多次
X{n}? X,恰好 n 次
X{n,}? X,至少 n 次
X{n,m}? X,至少 n 次,但是不超过 m 次
Possessive 数量词
X?+ X,一次或一次也没有
X*+ X,零次或多次
X++ X,一次或多次
X{n}+ X,恰好 n 次
X{n,}+ X,至少 n 次
X{n,m}+ X,至少 n 次,但是不超过 m 次
Logical 运算符
XY X 后跟 Y
X|Y X 或 Y
(X) X,作为捕获组
实验:
1 控制台输入验证方法实现:
1.1 定义方法
Location read(String msg)
Loaction 包含一个位置坐标: i, j
msg: 是输入提示信息,如: “输入坐标位置i,j”
1.2 要求:
如果输入错了要求反复输入
ij是一个16进制字符,
ij之间是“,”或者“空格”
^[0-9a-f](\s+|,)[0-9a-f]$
1,2
a,b
a b
a b
StirngBuilder 和StringBuffer
1 StirngBuilder 是Java5以后提供的,是一个新版本
性能好于StringBuffer。因为:StringBuffer 是线程
安全对象,方法需要检查线程的安全性,速度稍慢。
Java5 以后推荐使用StirngBuilder。
2 String 类的动态链接(+)的底层是使用StringBuilder
的append()实现。
Stirng a = "5";
String b = a+a+a+a;
String b = new StringBuilder(a).append(a)
.append(a).append(a).toSting();
字符串的动态会参数一个垃圾对象(StringBuilder)
问题代码:
Stirng a = "5";
a+=a;
a+=a;
a+=a;
优化:
Stirng a = "5";
StringBuilder buf = new StringBuilder(a);
buf.append(a);
buf.append(a);
buf.append(a);
a = buf.toString();
Java 包装类
1 实现基本类型<->对象类型的转换
int i=1;
Integer d = new Integer(i);
Object o = d;
2 提供一些工具方法
3 Java5 以后提供了自动包装(auto boxing)
Integer i = 1;// Integer i = new Integer(1)
Object o = 5;
Object o1 = 2.5;// new Double(2.5)
4 自动拆包(unboxing)
Integer i = 5;
int x = i+5;// x=i.intValue() + 5
Java中的时间
1 基本的时间表示:long
2 java.util.Date 是对long的包装。提供了时间的处理方法
getYear()
Date 类是Java早期的时间表示,Calendar(日历,历法)是新的
时间表示,Java推荐使用。
不过Date还是很普遍的在使用!
3 long <-> Date <-> Calendar
4 默认的日期创建,都是当前时间。
5 日期的输出与输入
6 Calendar 可以通过工厂方法 Calendar.getInstance()
来创建实例。
工厂方法:能够创建对象的方法都叫工厂方法。
经常用工厂方法创建接口或者抽象类实例。
工厂方法好处,可以屏蔽复杂的创建过程。
7 日期的计算
计算下个月的今天
计算这个月的第一天
class Person{
Calendar birthday;
}
大数运算
1 java.math.BigInteger 大整数
内部类
1 静态内部类:使用static修饰,声明在类体中,可以使用
外部类类名访问,在类内部可以省略类名。静态内部类中
可以访问外部类的静态成员。
2 成员内部类: 声明在类体中,不使用static,具有类的成员特征
也就是,必须有类的实例才能创建内部类实例。内部类实例
可以访问共享外部类的成员变量。很常用。
如:链表的节点就可以定义为内部类
3 局部内部类:把类声明在方法中,就是局部内部类,作用域
类似局部变量。很少见。
4 匿名内部类,匿名类:非常常见,可以写在任何地方,就行一般的语句。
语法更象是创建对象:
Date d = new Date(){};
匿名类是对原类的一个继承,同时创建了实例,{} 就是继承
以后的类体。类体中可使用机会所有类的语法。
被继承的类必须有无参数构造器!匿名类不能写构造器。
匿名类可以从抽象类或者接口继承,必须提供抽象方法的实现。
5 任何内部类都编译成独立的class文件
6 最大的作用:封装!
List 线性表
1 使用集合(List)作为属性时候,一般都直接实例化为空集。
2 可以使用泛型约束集合中元素的类型。线性表推荐使用泛型
List<Card> cards = new ArrayList<Card>();
3 ArrayList vs Vector 都是用数组实现的线性表
Vector 旧(Java 1.1)性能稍差,线程安全,内部数组成倍增长
ArrayList 新 (Java 1.2以后)非线性安全,性能好,增长50%
4 LinkedList 也是线性表实现, 采用双向循环链表实现。
private class Unit{
Object data;
Unit next;
Unit prev;
public Unit(int data) {
this.data = data;
}
}
HashMap 与 Hashtable
1 提供快速的散列查找实现。
2 初始化容量与加载因子。
初始化容量是散列空间大小,加载因子是指散列空间的充满率
如果超过充满率,HashMap会进行扩容并且重新散列。
3 HashMap 新的(1.2),非线程安全的,性能稍好,
可以保存在一个null的Key
Hashtable 旧的(1.1),线程安全,性能稍差,不允许存null。
Iterator 接口
1 是迭代器接口,是一个对集合进行遍历处理的模型。
就是,把集合中的元素从头数一遍。
2 非常适合与while、for组成模式化的迭代处理代码。
一定合理覆盖实现hashCode和equals,保证集合API的工作正常
排序二叉树
1 TreeSet TreeMap
自然排序:
1 类实现了Comparable表示这个类实例是可以比较大小的。
可以比较大小的对象List集合,可以利用Collections.sort
进行自然顺序排序。
2 Comparable 的实现,要实现compareTo方法。
这个方法要与equals和hashCode方法的实现一致:
compareTo 返回结果为0时候,equals的结果一定是true
hashCode值一定一样!
3 Java提供的很多类都实现了Comparable, 如:String,
包装类,StringBuilder,Date,等。
@Override 是JDK5以后提供的注释语法,可以告诉Java编译器
检查随后的方法是否符合方法覆盖的语法。
在List中交换元素:
1 Collections.swap(cards, i, j);
2 Card c = cards.get(i);
c = cards.set(j, c);
cards.set(i, c);
3 cards.set(i, cards.set(j, cards.get(i)));
Collections 是集合的工具类
1 排序
2 查找
3 填充
4 交换
5 洗牌
Java GUI
1 Swing 图形界面包:javax.swing.* java.awt.*
2 JFrame 代表图像界面窗口
3 JPanel 是窗口中的一个矩形区域,一般需要指定布局管理
4 Layout 是布局, 布局:是指界面中组件元素的相对位置
布局的具体实现有:BorderLayout 边框布局
FlowLayout: 顺序流式布局
5 在窗口中显示内容必须放置一个JPanel实例
6 如果需要复杂的姐妹布局,一般采用Panel中套Panel实现
关于事件监听
事件源对象,是事件发生时候的触发对象。