Java第一天 2007年4月23日
1、Java之父Golsling
1995年5月23日 Java诞生
1998年12月 1.2版本 Java2 J2SE J2EE J2ME
2004年12月 1.5版本(5.0) Java JavaSE JavaEE JavaME
2、Java SE --- Java标准平台
Java EE --- 企业级平台
Java ME --- 微小平台,用在资源受限的平台上
3、(1)跨平台 --- 一次编译,到处运行
(2)简 单 --- 简化C++,取消了指针,对指针进行了上层的封装,它保证能够通过这个指针(引用),来访问有效的内存单元。
不允许多继承,使继承关系成树装图,每个类都只能由一个父类。
java语言的开发效率高,但执行效率低。(相当于c++的55%)
(3)纯面向对象的语言 --- 都要放在类中
(4)垃圾回收机制 --- 自动垃圾收集,永远不会出现内存泄露的问题
4、虚拟机
java语言是先编译后解释,java源码是通过编译生成一种特殊的.class的中间字节码文件,然后再由JVM进行解释运行。
(编译) (解释)
.java ----> .class ---> 可执行文件
所以效率低,是C++的20倍
5、java源代码中的main方法的定义写法。main方法是程序的入口。
p lic class Hello{ //一个源文件中只能有一个公开类,而且源文件的文件名与公开类的类名完全一致
p lic static void main(String[] args){ //程序入口 p lic static 可以调换顺序
System.out.println("Hello world"); //打印语句
}
}
编译命令 javac xxxx.java 源文件的名字,源文件中的一个类会对应编译生成一个.class文件
运行命令 java xxxx 类的名字 --- 启动虚拟机
6、环境变量
JAVA_HOME = /opt/jdk1.5.06 JDK 安装路径 --- JDK = JRE {JVM(硬件)+编译器(软件)} +编译器工具+类库
PATH = $Path:$Java_Home/bin:.
ClassPath = . 类路径
7、包 --- 分类放置,减少命名空间
包名.类名 表示一个类的全限定名
java xxx.xxx.ClassA --- 运行时要在包结构的上一层目录来运行。
javac -d . xxxx.java --- 编译的时候,按照包结构存放字节码文件,此命令生成的.class文件在当前目录
package xxx.xxx,包的定义在一个程序中只能由一个
import xxx.xxx.xxx.ClassA; --- 在程序中声明ClassA类,使用的时候不需加包名,使用同一包内的类时,不用引入
import p1.p2.p3.p4.p5.*; --- 声明p5包中所有的类,不能代表其子包
系统会在每个java程序中隐含导入了java.lang这个包
8、java中的注释,
单行注释 //......
多行注释 /* .......*/
文档注释/** ........<p>(换行标签)*/,用javadoc命令可以根据原码中的文档注释生成注释文档(html格式)。文档注释中可以使用html标签。
javadoc -d 路径(指定注释文档的保存路径) xxx.java
文档注释一般写在类定义之前,方法之前,属性之前。
在文档注释中可以用 @author 表示程序的作者,@version 表示程序的版本,前两个注释符号要写在类定义之前,用于方法的注释@param 对参数进行注释,@return 对返回值进行注释 @throws对抛出异常的注释。
10、标识符规则 --- 类,方法,变量,同时也是包名的规范
由字母(汉语中的一个汉字是一个字母),数字,下划线和货币符号组成,不能以数字开头。
大小写敏感
没有长度限制,不能有空格
不能使用Java的关键字和保留字
java中的关键字
goto和const在java中虽然不再使用但是还作为保留字存在
java中没有sizeof这个关键字了,java中的boolean类型的值只能用tr 和false,且这两个也是关键字
enum 枚举 assert 断言
一个标识符尽量符合语义信息,提高程序可读性
类 名 :每个单词首字母大写,
变量和方法 :第一个单词小写,后边的每个单词首字母大写
包 名 :全部小写
常 量 :全部大写
11、局部变量:定义在方法中的变量
(1)先赋值后使用
(2)从定义变量的代码块开始到代码块结束
(3)在同一范围内不允许两个局部变量发生命名冲突
* * * *
Java第二天 2007年4月24日
1、Java的数据类型
(1)简单类型 --- 8种有符号的数据类型
a) 整型
byte 1字节 8位 -128到127
short 2字节 16位 -2^15到2^15-1 -32768 到 32767
int 4字节 32位 -2^31到2^31-1 -2147483648 到 2147483647 整型值存放,正数存放原码(二进制码),负数则存放补码(原码按位取反末位加一)。
long 8字节 64位 -2^63到2^63-1 long a = 40000l; //在数字的结尾加“l”,表示long类型的字面值
b) 浮点类型
float 4字节 32位 float a = 1.3f;
do le 8字节 64位 do le a = 1.3;
do le和long比较,do le 表示的数值要大,因为有科学计数法
float a = 1.3; //error 会造成精度丢失,强转float a = (float)1.3;或者float a = 1.3f;
c) 字符类型
char 2字节 16位
d) 布尔型
boolean false/tr //Java中false与不能转换
自动类型提升:
a 运算符 b
a和b中有一个是do le , 结果就是do le
a和b中有一个是float , 结果就是float
a和b中有一个是long , 结果就是long
除以上之外的情况,结果都是int
char是无符号的16位整数,字面值必须用单引号括起来; ‘a’
String 是类,一个String的字符串是一个对象,非原始数据类型;
在字符串中使用"+",表示字符串的连接,系统重载了这个运算符
char类型也可以用通用转译字符,但是不能用ASCII码。可以用“\”(十六进制)这种格式,因为char型中使用的是unicode编码方式。
char c1 = 'a';
char c2 = 97;
char c3 ='\a'; //一个字节用2个十六进制的数字表示
整数除有异常,do le除没有异常
(2)对象类型
2、java中的运算符(java的运算符的优先级和结合性和c++相同)
*** System.out.println(3/2) 按整型计算 得1 ***
byte a = 1;
a=a+2; //不合法,自动类型提升,赋值丢失精度
a += 2 ; //不会发生自动类型提升的,合法
a++ ; //不会发生自动类型提升的
1) >>= 前面是零补零,前面是一补一; 右移一位比除以2效率高
2) >>>= 无符号右移(强制右移都会移进零),
>>=和>>>=对于负数不一样
正数:右移n位等于除以2的n次方
负数:变成正数。
3) && 短路与,前面为假,表达式为假,后面的操作不会进行,& 非短路运算符,会对所有条件进行判断。
例: int a = 4;
if(a<3&(b=a)==0) b赋值
if(a<3&&(b=a)==0) b不赋值
4) || 短路或,前面为真,表达式为真,后面的操作不会进行,| 会对所有条件进行判断。
5)instanceof,是用于判断一个对象是否属于某个类型
6)java中的求余运算符“%”可以对两个实型变量求余 5%2=1
3、流程控制
(1)控制流
if()
if()….else
if()…..else if()….else
注意:else只是和其上面的同层的最近的if()来配对。
(2)switch(s){
case 'a':……..
case 1:……break;
default:
…………
}
注意:switch()内数据类型为byte short char int类型,只有以上四种类型的才可以在switch()中使用。
case块中不加break时顺序执行下面的语句。
4、循环语句
for(int i=0;i<n;i++){} ---- 确定循环
while(){} ---- 循环或多次
do{} while();-----------注意加分号 循环1或多次
5、语法
在main方法中要使用全局变量或调用其他方法时,要求全局变量和方法要有static修饰
命令行参数 java Class a b
args[0] = a
args[0] = b
字符串转成int类型 int i = Integer.parseInt(a);
6、数组
内存中的连续空间
数组是一次性定义多个相同类型的变量
Java中一个数组就是一个对象,有属性,没有方法
int[] a; //定义一个数组,变量名就是指向数组首地址的指针
a=new int[10]; //为数组分配空间
a.length; //得到数组的长度
数组创建后有初始值:数字类型为0 布尔类型为false 引用类型为null
String[] 默认值 null
初始化、创建、和声明在同一时间
int[] i = {0,1}; //显示初始化
int[] i = new int[]{0,1}; //注意:这样显示的初始化的时候,new int[] 中括号中必须是空的,不能填数字
Car[] c = {new Car(),new Car()};
数组拷贝
System.arrayCopy(Object src, int srcPos, Object dest, int destPos, int length);
src源数组,srcPos从第几位开始拷贝(数组下标,从开始),dest目标数组,destPos目标数组放置的起始位置,length,表示要拷贝的长度。拷贝一个数组到另一个数组。
多维数组
1) 有效定义
int[][] i1 = new int[2][3]; (同时给定一维,二维的空间)
int[][] i2 = new int[2][]; (给定一维的空间,二维空间待定,不规则的二维数组)
i2[0] = new int[2],i2[1] = new int[3];
* C++中 int[][] =new int[][3];有效
2) 无效定义
int[][] i1 = new int[][3];
3) 数组长度 ------------数组的属性length(在二维数组中这个属性只代表第一维的长度)
int[] i = new int[5];
int len = i.length; //len = 5;
St?nt[][] st = new St?nt[4][6];
len = st.length; //len = 4;
len = st[0].length; //len = 6;
练习:(1)数组元素的偏移
在使用数组的时候,通常使用一个辅助变量纪录数组中的有效元素的个数,还表示下一个可插入位置的下标
(2)数组元素的轮换
偶数个球队足球比赛,每个队和每个队有且只有一场比赛
把数字按"U"字型摆放,左边最上边的数字不变,其他数字按逆时针旋转
(3)有一个奇阶的方阵,填如数字,使得
第一个数一定放在第一行的最中间,第二个放在右上方,行越界,放在此列的另一侧,列越界放在此行的另一侧
行列都越界的时候,退回来,放在原来的数字下边,当要放入的地方有数字的时候,退回来,放在原来的数字下边
(1)
p lic class ArrayInsertDelete{
static int[] a={1,2,3,4,5,6};
static int index=6;
static void insert(int pos,int val ){
if (index==a.length) expand();
for(int i=index;i>pos;i--){
a[i]=a[i-1];
}
a[pos]=val ;
index++;
}
static void delete(int pos){
index--;
for(int i=pos;i<index;i++){
a[i]=a[i+1];
}
}
static void expand(){
int[] b=new int[a.length*2];
System.arraycopy(a,0,b,0,a.length);
a=b;
}
static void print(){
for(int i=0;i<index;i++){
System.out.print(a[i]+"\t");
}
System.out.println();
}
p lic static void main(String[] args){
print();
insert(2,7); //{ 1,2,7,3,4,5,6}
print();
delete(4); //{1,2,7,3,5,6}
print();
}
}
Java第三天 2007年4月25日
1、面向对象的思想
anything is an Object(万物皆对象)
符合人们客观看待世界的规律
2、抽象,从对具体的对象中抽取有用信息。
对象有其固有属性,对象的方法,即对象的行为(对象能做什么)
对象本身是简单的(功能简单),多个对象可以组成复杂的系统(对象之间彼此调用对方的方法)
3、面向对象的优点
1)对象应当是各司其职(功能简单),各尽所能(把自己的功能作到最好)。(弱耦合性实现了前面所述的对象的特点)
2)对象的耦合性,是对象之间的联系,对象和系统之间的联系。
对象的耦合性要尽量的弱,也就是对象之间的联系尽可能的弱,对象和系统之间的联系尽可能的弱。
弱耦合性要通过一个标准来实现
3)可重用性
对象的功能越简单,复用性就越好。(对象的耦合性弱,复用性就比较强)
4)可扩展性
系统的可插入性,是在系统中加入新的对象之后的系统稳定性。
对象的可替换性,是在系统中替换原有的对象之后的系统的稳定性。
4、面向过程和面向对象的比较
面向过程是先有算法,后又数据结构 --- (怎么解决问题)
面向对象是先有对象(数据结构),后有算法(对象间的方法调用) --- (用什么做)
5、类的定义
1)属性
类型 变量名; --> 实例变量,系统赋初始值
默认值 使用范围 命名冲突
实例变量 系统赋初始值 在类的内部使用 允许实例变量和局部变量发生命名冲突,变量的值->局部优先
局部变量 先赋值后使用 定义他的代码块 同范围内不允许两个局部变量发生命名冲突
2)方法的定义:
不允许方法的声明和实现分开
方法声明的组成:
(a)方法的修饰符(或多个修饰符出现的顺序无关) |
(b)方法的返回值类型 |顺
(c)方法名 |序
(d)方法的参数表 |向
(e)方法中允许抛出的异常 |下
V
6、方法的重载
java中方法的重载(overload)方法名相同,参数表不同(个数,类型,排列顺序),其他部分可以不同。
调用时要给出明确参数并确定调用某一方法。在编译时,编译器会根据参数选择适当的方法,所以重载也叫编译时多态。
** 方法的重载可以屏蔽一个对象同一类方法由于参数不同所造成的差异 **
向上就近匹配原则
如果方法的参数表中的数据类型和调用时给出的参数类型不尽相同时会根据向上匹配的就近原则。(类型就近向上转化匹配)
p lic void m(byte a,short b){
System.out.println("m(byte,short)");
}
p lic void m(short a,byte b){
System.out.println("m(short,byte)");
}
此时若用2个byte作为参数调用m()方法,编译会出错,因为按照向上就近匹配原则,提升哪个都可以,出现语义不明确的错误
7、构造方法
1)方法名与类名相同,无返回值
2)系统提供默认无参的,空的构造方法
3)若自定义一个有参的构造方法,则系统将不提供无参的,空的构造方法
不能手工调用,在一个对象的生命周期中,只会被调用一次
8、对象的创建
Java在堆中创建对象的过程:
1)分配空间
2)初始化属性,若声明实例变量的时候没有初始化,用默认值初始化属性
3)调用某个构造方法(前提:不考虑继承关系)
St?nt s; //声明一个St?nt类的对象变量
s = new St?nt(); //调用St?nt类的无参的构造方法,创建一个对象,把这个对象的地址赋给一个St?nt类的引用
(引用指向了这个对象,引用中保存对象的首地址,以后都是通过引用访问这个对象的属性和方法)
s.age s引用所指向的对象的age属性
9、变量
包括简单变量(原始数据类型),对象变量。
简单变量传值,对象变量传址!
static void method3(St?nt s){
s=new St?nt(); //创建一个新对象,把对象的地址赋给形参的引用
s.age=20; //改变新对象的状态
}
St?nt stu=new St?nt();
System.out.println(stu.age); // 打印出St?nt类的age属性的初始值
method3(stu); //method3方法返回,形参s指向的被改变的对象已经成为了垃圾对象
System.out.println(stu.age); //打印的仍是原来那个对象的age的值
10、this
是一个引用,指向的是自己,即当前对象(哪个对象调用了方法,哪个对象就是当前对象)
可以用来区分实例变量和局部变量。this.age = age ;
this(),他表示调用本类其他的构造方法,注,只能写在构造方法的第一行。
项目练习:
项目名称:Bank Account Management System 银行账户管理系统 简称BAM
项目描述:这是一个基于C/S结构的银行账户在线管理系统,用户可以通过ATM终端界面来操作自己的银行账户.
项目实施方式:这是一个同步练习,随着达内CoreJava课程的深入,这个项目将趋于完整,学员的任务是随着知识点的深入,完成每一个进阶的项目要求.
练习1:
(面向对象基础语法)
写一个账户类(Account)
属性:
id:账户号码 长整数
password:账户密码 String
name:真实姓名 String
personId:身份证号码 String
email:客户的电子邮箱 String
balance:账户余额 do le
方法:
deposit: 存款方法,参数是do le型的金额
withdraw:取款方法,参数是do le型的金额
构造方法:
有参和无参,有参构造方法用于设置必要的属性
Java第三天 2007年4月25日
1、复习
面向对象思想
符合我们看待客观世界的规律
Everything is an object
对象:客观存在,有什么(属性),能做什么(方法)
每个对象都是简单的,有简单的对象拼装成复杂的系统
面向对象的优点:
1)各司其职,各尽所能
2)弱耦合性
3)可重用性,可扩展性
类:对象共性的抽象,客观对象在人脑中的主观反映
对象的模版
属性:在类里,但在任何方法之外定义的一个变量 --- 实例变量
有默认值,访问范围,至少是本类内部,可以和局部变量发生命名上的冲突,局部优先,this区分
方法:方法定义(声明对象能做什么)/方法实现(怎么做)
定义:修饰符 返回值类型 方法名 (参数表) 抛出的异常
重载(Overload):方法名相同,参数表不同。
编译时多态,编译器根据参数表选择一个方法
为什么要有方法的重载?
屏蔽一个对象同一类方法由于参数表不同所造成的差异
就近向上匹配
构造方法:没有返回值,方法名和类名是相同的,系统提供默认无参的空的构造方法,** 建议自己写无参构造
构造对象的过程:
1)分配空间
2)初始化属性
3)调用构造方法
类名 引用名=new 类名(构造参数);
方法参数传递规则:
简单类型参数:传值
对象类型参数:传引用,实参和形参指向同一个对象
2、面向对象的三大特征:封装、继承、多态。
java中的封装
封装,一个对象和外界的联系应当通过一个统一的接口,应当公开的公开,应当隐藏的隐藏。
(对象的属性应当隐藏),一个对象的内部是透明的,就是把对象内部的可透明性和隐藏的特性区分开,该透明的透明,该隐藏的隐藏。
(封装的属性)java中类的属性的访问权限的默认值不是private,要想隐藏该属性或方法,就可以加private(私有)修饰符,来限制只能够在类的内部进行访问。
对于类中的私有属性,要对其给出一对方法(getXxx(),setXxx())访问私有属性,保证对私有属性的操作的安全性。
方法的封装,对于方法的封装,该公开的公开,该隐藏的隐藏。方法公开的是方法的声明(定义),即(只须知道参数和返回值就可以调用该方法),隐藏方法的实现会使实现的改变对架构的影响最小化。。
封装会使方法实现的改变对架构的影响最小化。
完全的封装,类的属性全部私有化,并且提供一对方法来访问属性。
Java Bean 一种组件规范 --> 所有属性私有,访问方法按照命名规范setXxx(),getXxx()方法
3、java中的继承
继承,是对有着共同特性的多类事物,进行再抽象成一个类。这个类就是多类事物的父类。父类的意义在于可以抽取多类事物的共性。
泛化:把共性从子类中抽取出来。
特化:现有父类,再有子类的过程
父类与子类 -> 从一般到特殊的关系
java中的继承要使用extends关键字,并且java中只允许单继承,也就是一个类只能有一个直接的父类。
这样就是继承关系呈树状,体现了java的简单性。
子类只能继承在父类中可以访问的属性和方法(实际上父类中私有的属性和方法也会被继承但子类中无法访问罢了)。
实际上一个子类对象中包含一个父类对象
访问控制修饰符:(可以修饰属性和方法)
private修饰符,表示只有本类内部可以访问,不能继承。
default修饰符,方法不加修饰符,会默认为default,表示在同一个包中可以访问,父子类在同一包中,子类可以继承父类的相应内容。(可以修饰类)
protected(保护)修饰符,表示同一包中可以访问,不同包的子类也可以访问继承。
p lic修饰符,表示公开,在任何地方都可以访问,能继承。(可以修饰类)
修饰符的权限是由上而下逐渐变宽的。
继承的意义,就在于子类可以在父类的基础之上对父类的功能进行发展,继承可以使系统的耦合性降低,也就是使对象间的联系便的松散,使多类对象间的联系用其父类对象代替。
注意:构造方法不能被继承。
父类的属性及方法的确定:要从子类的角度来看子类间的共性,当所有子类都有这个属性时,就应当考虑是否该放在父类中,方法也是如此,方法可以被看作是对象的行为,而类的方法这时这一类对象所共有的行为,所以也应当在方法的确定时注意是不是所有的子类型中都需要有这种方法,并且会根据不同的类型的行为的方式也不同才可以覆盖着个方法。
4、java中方法的覆盖
子类中有和父类中可访问(可继承到子类)的同名同返回类型同参数表的方法,就会覆盖从父类继承来的方法。
在父子类中,出现方法名相同,参数表不同的情况,叫方法的重载
方法覆盖父子类返回值类型也要相同
注意:在jdk1.4以前要求方法的覆盖时,需要方法的返回值,参数表,方法名必须严格相同,而在jdk1.5中方法覆盖,子类的中覆盖的方法的返回值可以是父类中被覆盖的方法的返回值类型的子类型。
注意:子类的方法覆盖父类的方法时,方法的修饰符要么相同,要么子类中的方法的修饰符表示的访问权限要宽于父类。父类中的私有方法,不能被继承到子类,就是说子类中即使将其覆盖了也不会有多态。
注意:父子类中有同名的属性不叫子类覆盖了父类的属性,这种情况较作属性的遮盖(shadow)。
5、super关键字
(1)区分父子类间的属性遮盖和方法覆盖
(2)super(),表示在子类的构造方法中调用父类的构造方法(可以通过这种方法在子类的构造方法中初始化父类中的属性),super()也只能出现在构造方法的第一句上。super(),在子类的构造方中指明构造父类时调用哪一个父类的构造方法构造父类。
super,这里所表示的是一个父类的对象,可以通过super来使用父类中可以访问的方法(可以在父类中定义setXxx(),getXxx()方法来访问父类中的私有属性),super可以屏蔽父子类中同名属性的冲突。
注意:在写类的时候,一定要写默认无参的构造方法,如果一个构造方法的第一句既不是this(),也不是super()时,那么就会在这里隐含的调用他的父类的无参的构造方法,即隐含的有super()。
6、创建对象的过程
1)递归的构造父类的对象,默认调用父类无参的构造方法super()
2)分配本类空间
3)初始化本类实例变量(属性)
4)调用本类的构造方法
7、java中的多态 --- 运行时多态
Animal a = new Dog(); //引用类型可以是对象类型的父类
对象类型 客观类型
引用类型 主观类型
以子类覆盖了父类的方法为前提
1)对象类型不变
2)只能对一个对象调用引用类型中定义的方法
3)运行时会根据对象类型找覆盖之后的方法
Animal a = new Dog();
Dog d = new Dog();
a = d; //把子类引用赋值给父类引用,是合法的
d = (Dog)a; //把父类引用赋值给自类引用,需要强转
引用 instanceof 类名 //判断前面的引用和后面的类是否兼容
可以翻译为“是不是”
a instanceof Dag; //a指向的对象是不是Dog类
一般用在强制类型转换之前,避免转换异常
多态可以使代码变得更通用,以适应需求的变化。也就是定义在父类中的方法,可以在子类中有不同的实现将其覆盖,在为父类型的对象变量赋值相应需要功能的子类的对象实例。
可以屏蔽不同子类的差异
作业:
1.设计一个形状类,方法:求周长和求面积
形状类的子类:Rect(矩形),Circle(圆形)
Rect类的子类:Sq re(正方形)
不同的子类会有不同的计算周长和面积的方法
创建三个不同的形状对象,放在Shape类型的数组里,分别打印出每个对象的周长和面积
2.某公司的雇员分为以下若干类:
Employee:这是所有员工总的父类,属性:员工的姓名,员工的生日月份。方法:getSalary(int month) 根据参数月份来确定工资,如果该月员工过生日,则公司会额外奖励100元。
SalariedEmployee:Employee的子类,拿固定工资的员工。属性:月薪
HourlyEmployee:Employee的子类,按小时拿工资的员工,每月工作超出160小时的部分按照1.5倍工资发放。属性:每小时的工资、每月工作的小时数
SalesEmployee:Employee的子类,销售人员,工资由月销售额和提成率决定。属性:月销售额、提成率
BasePlusSalesEmployee:SalesEmployee的子类,有固定底薪的销售人员,工资由底薪加上销售提成部分。属性:底薪。
写一个程序,把若干各种类型的员工放在一个Employee数组里,写一个函数,打印出某月每个员工的工资数额。注意:要求把每个类都做成完全封装,不允许非私有化属性。