一、 java的特点
1. 简单,易懂,易学,易用
2. 面向对象,符合人类自然的思维模式,封装,继承,多态,类,接口概念清晰
3. 与平台无关
- 由JVM提供JRE来运行java
- 平台一般指硬件加上软件的平台,即机器加上操作系统【OS+CPU】
- 基于java的JVM和字节码,JVM可以直接识别和执行字节码
4. 内置多线程,做异步调用非常方便
5. 安全
6. 动态,类的引入后,在运行时动态装载
二、JDK的安装
1. 开发工具箱即jdk,运行环境即jre,提供运行环境的即jvm
java.exe 运行器/解释器
java -jar …jar执行jar包
javac.exe 编译器
javap.exe 反编译器
javadoc.exe API文档生成
2. 系统环境变量
- 配置jdk本身的目录,得到环境变量JAVA_HOME
- 设置path,指到jdk安装目录下的bin目录
因为编译器javac.exe和解释器java.exe都在该目录下 - 设置classpath,指到jdk安装目录下的jre目录
因为java应用程序运行时所城要的java类库都在这个目录下,即\jre\lib\rt.jar包;
一般不需要配置这个目录,但如果因为安装过别的商业产品改变了这个值,就要重新配置一下。
配置的目录一般为
%JAVA_HOME%\jre\lib\rt.jar;.;
.; // 是指可以加载应用程序当前目录中的类
3. 建议下载源码包,在eclipse中指定源码包的位置,方便点击查看源码
三、JAVA的程序
- 有一个主类,即main函数(方法)所在的类
public static void main(String args[]){}
- java解释器执行的类名必须是主类的名字(可以带上目录,但没有扩展名)
- 执行过程
- JVM加载字节码到内存
- 解释执行字节码文件
- 从main方法找到入口地址,开始运行程序
- java的应用程序是一个工程,即一个项目,一般由若干个类构成
- java程序以类为基本单位
- 每一个源文件都是一个独立的编译单位【编译角度】
- 改一个源文件,不必重编译其它类,通用的代码,可以复用【软件工程角度】
四、注释部分
- 加注释的目的是为了代码的维护和易读
易读才方便维护和升级 - 先写注释是一个良好的编码习惯
- 不断地重构和整理注释是一个进步的习惯
- 注意也是编码风格的一部分
- 两种风格Allmans和Kernighan
Allmains风格
class MyClassName
{
public static void main(String args[])
{
}
}
Kernighan风格
class MyClassName{
public static void main(String args[]){
}
}
五、标识符
- 长度不限,但由字母,下划线,美元符号和数字组成
- 第一个字符不能是数字
- 不能与关键字冲突int,String【有50个keyword】
- 不能与运算符冲突true,false
- 区分大小写,可以是unicode字符(中文,但这样做很SB)
六、基本数据类型
- 逻辑类型 boolean
true
false
- 整型数据 byte,short,int,long
123
123456789L
- 字符数据 char
‘a’
‘A’
‘\n’
‘\t’
- 浮点数据 float,double
123.0f
256.5F
123.0d
258.456D
- 空值 null
- 基本数据类型可以做强制转换
int x = (int)123.456;
long y = (long)456.456F;
int x = (int )1999L;
byte a = (byte)128;
float x = (float)1234.3;
七、命令行中的输入、输出
- 使用Scanner对象来完成
- 具体方法
nextBoolean()
nextByte()
nextShort()
nextInt()
nextLong()
nextFloat()
nextDouble()
- 输出直接用System.out.println()或是System.out.print()
- 直接输出文本
System.out.println(myVarNameString+“的值是:”+myVarValue);
- 格式化输出文本
System.out.printf("%d%f%c",12,12.12,‘a’);
八、数组
- java不允许在数组声明时,在方括号内指定数组元素的个数
- 声明时只给出元素类型和数组名字
- 在new的时候才具体给出来需要的内存空间大小
- 允许在new的时候,以变量的形式来指出元素的个数【动态数组】
- 数组的索引是从0开始的
- a数组的长度,用a.length可以直接取出来
九、枚举类型
- 在JDK1.5之后引入的类型
- 用enum eName{}形式来定义,常量列表用逗号间隔
enum Month{
Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec
}
enum Week{
Mon,Tue,Wed,Thu,Fri,Sat,Sun
}
enum Season{
Spring,Summer,Autumn,Winter
}
- 直接打点使用即可
Year myMonth;
myMonth = Year.Oct;
十、instanceof运算符
它是一个二目运算符号
Object o = list.get(1);
if (o instanceof Person) {
Person s = (Person)o;
}
要特别注释,在做类的强制转换时,经常要用这样的形式先做判断
o instanceof Person
- 左边的操作元是一个对象
- 右边的操作元是一个类
- 如果对象是类或子类的对象,则返回true,否则返回false
十一、分支语句
1. if
- if
- if else
- if else if else
2. switch
switch(expression){
case value1:
若干语句
break;
case value2:
若干语句
break;
...
case valuen:
若干语句
break;
default:
若干语句
break;
}
最常见的用法是与枚举值配合来用
switch(Season){
case Spring:
System.out.println("春季,春开花会开");
break;
case Summer:
System.out.println("夏季,我会在荷叶处等你到来");
break;
case Autumn:
System.out.println("秋季,丰收的果实在招唤");
break;
case Winter:
System.out.println("冬季,瑞雪将我无痕地引向世外");
break;
}
十二、循环语句
for
int i;
int sum = 0;
for(i=0;i<10;i++){
sum = sum + i;
}
System.out.println('累加求和是:'+sum);
while
int i = 0;
int sum = 0;
while(i<10){
sum = sum + i;
i++;
}
System.out.println('累加求和是:'+sum);
do-while
int i = 0;
int sum = 0;
do{
sum = sum + i;
i++;
} while(0<10);
System.out.println('累加求和是:'+sum);
break and continue
- break结束该重循环
- continue结束该次循环
- for与数组的结合使用
for(int var:intArrayName){…}
- for与枚举类型
for(Season tmpSeason:Season.values()){…}
for(Week tmpWeek:Week.values()){…}
for(Month month:Month.values()){…}
十三、类与对象
封装、继承、多态
- 将数据和操作封状在一个类中
- 子类可以继承和扩展父类的属性和功能
- 类内部重载【Overload】实现同一操作名的方法上多态;类继承覆盖【重写Override】实现同一操作名在不同对象上的多态;
- 重载用参数列表来区别:个数,类型,顺序
- 重写用子类来实现
类名,类体
- 类名大写
- 类中,变量表示属性;方法表示功能;
class Person{
...
}
- 成员变量VS局部变量
- 类(静态)变量VS对象(实例)变量
- 复杂类型:包装类型,列表等
实例变量【普通】与类变量【静态】
实例方法【普通】与类方法【静态】
- 对成员变量的操作只能放在方法中,方法可以对成员变量和该方法体内的局部变量进行操作;
- 实例方法既能对类变量操作也能对实例变量进行操作;类方法只能对类变量进行操作;
- 一个类中的方法可以相互调用;实例方法可以调用该类中的其他方法;类方法只能调用类中的类方法,不能调用实例方法;
使用对象,打点操作
- 对象操作自己的变量(即属性)
- 对象操作自己类中的方法 (即功能)
- 对象本身在堆内存中,而对象的引用在栈内存中;
- 没有实体的对象即空对象,空对象不可以使用,报空指针异常
- 具有相同的引用,则具有完全相同的实体
可变参数
- 是JDK1.5以后的新功能
- 可变参数是个数可变,但类型必须都相同
- 用…来表示若干个参数
public void fun1(int … x)
public void fun2(double a,double b,int … x)
- 使用时,跟数组元素使用一样,用下标来取x[0],x[1]…下标从0开始
一个类可以把对象作用为自己的成员变量
- 即has -A的方式产生的关联关系
- 例如:圆柱有底面,长方体有底面积,人有姓名和出生年月日,头有眼耳口鼻
static关键字的理解
- 它修饰的方法是类方法、静态方法
- 它修饰的成员是类属性、类变量、类成员、静态成员
- 不用它的就是实例的,对象的
- 所有对象的类成员部分都分在相同的一处内存中,是共享的
- 类方法可以用类直接调用,也可以用对象来调用
用类名来调用,就与过程化编程很类似了,看似打破了封装,但达到共享数据,完成通信的目的 - 实例方法只能用对象来调用,不能用类名来调用
包
- 是有效进行类管理的机制
- 包的管理也是用的语句
package com.fhzheng;
- 包最终转化为目录来存类文件
- 运行时,必须写类的全限定名,即带有包名的类名
c:\java com.fhzheng.demo.Hello
- 建议用自己所在的组织的域名倒置做包名
- 用import方式引入类库中的类
java.lang
java.swing
java.io
java.util
java.sql
java.net
java.applet
设计一个类,比如三角形
- 类名
- 属性有哪些,三条边
- 方法有哪些,设置三条边,求周长,求面积
访问权限
- 用一个类创建了一个对象之后,该对象可以通过“打点”的方式,操作自己的变量,使用自己的方法。
- 但变量和方法有一定的限制
1. 私有变量、私有方法private,只有该类的对象自己可以用
2. 默认变量、方法,即不加修饰,同包的类的对象可以用
3. 友好变量、方法 protected,只有同包和友元【子类】可以用
4. 公有变量、方法 public,都可以用
封装类型==基本类型的封装
- Double
- Float
- Byte,Short,Integer,Long
- Character
自动装箱和拆箱:基本数据类型和相应的对象之间相互自动转换的功能
十四、继承与接口
14.1 由已有的类来创建新的类的机制
- 子类和父类在同一包中的继承:除private之外的变量和方法都可以继承
- 子类和父类不在同一包中的继承:只继承protected和public的变量和方法
14.2 子类对象的构造过程
- 先调用父类的某个构造方法
- 父类的private成员会分配内存,但不作为子类的对象的变量
14.3 子类重写父类的方法
- 名称类型保持一致
- 可以隐藏继承的方法
- 可以把父类的状态或是行为改变为自身的状态和行为
- 重写的方法可以操作从父类继承过来的变量,也可以操作子类新声明的成员变量
- 可以使用super关键字来调用父类的构造方法
- 使用super可以找到【父类】被子类隐藏了的属性和方法
14.4 final关键字
- 修饰:类,成员变量,成员方法,局部变量
- 类不能被继承
- 方法不能被重写
- 成员变量或是局部变量就成了常量—不能再变
14.5 对象的向上转形
- 说狗是动物是可以的,但说动物是狗就不可以了
- 狗是动物的一种
- 动物是父类,狗是动物的子类
- 也就是说,狗是可以转型为动物的,而动物不可能转型为狗
- 也就是说,子类是可以转型为父类的,而父类不可能转型为子类
- 向上转型后,不能操作子类新增的成员变量
- 向上转型后,可了访问子类继承或隐藏的成员变量===>接口实现后就可以用
14.6 继承与多态
- 上转型之后的某个方法,可能有多种实现,这就是多态的基础
- 子类在重写父类的方法时可能产生不同的行为
- 如:动物都会发出叫声
- 狗发出的是“汪汪汪”
- 猫发出的是“喵喵喵”
- 羊发出的是“咩咩咩”
- 多态是指父类的某个方法被其子类重写时,各自产生自己的功能行为
- 在应用上,即多个子类对象【不同的对象】收到相同的消息时,做出不同的反应
14.7 抽象类和接口
- 抽象类是对抽象本身的概念实现,它的标识是有抽象方法给出
- 因为是抽象的抽象,所以不能new它的对象,只能new具体类
- 抽象方法只关心:方法名,参数,返回类型,不关心方法体【不关注具体实现】
- 提供了一种多态实现机制:开闭原则实现
- 上转型对象所在的类不需要做任何修改就可以调用子类重写过的方法
- 类是单继承
- 接口是对功能的抽象,一般它就只有方法IO描述,一旦被实现,就可以直接new实现类来用
- 接口可以实现多继承
- 接口一般只考虑方法【功能】
- 子类实现多个接口的目的,就是要具有多个功能
- 子类实现某个接口,必须重写该接口的所有方法
- 接口可以被接口继承
- 接口可以被类实现
- 接口可以实现为抽象类,本质上是实现方法集的过滤和选择
- 抽象本身是一种化简模式和方法
14.8 接口回调
- 具体动作:把实现某一接口的类创建的对象【子类对象】的引用赋给接口声明的接口变量【接口对象】中,那么该接口变量就可以调用被类重写的接口方法【已经实现了的方法】,这就是接口回调
- 接口回调时,可能会有多种形态,即多态
- 接口充分体现了“开闭原则”,对扩展开放,对修改关闭
接口与抽象类的比较
- abstract类和接口都可以有abstract方法;
- 接口中只可以有常量,不可以有变量,集中火力给出方法规范;而抽象类中概可以有常量,也可以有变量,与普通类比,一定要多出至少一个抽象方法;
- 接口中,应该全是抽象方法:即只给方法名,参数个数类型,返回类型即可;而抽象类里,可以有普通方法
十五、内部类
- 内部类的形成
- 外部类名$内部类名
- 类是一种数据类型,如果用static修饰了内部类,则内部类就成了外嵌类的一个静态数据类型【即类类型】,只能用类名来访问,不能用对象来访问
- 非内部类不可以是static类
十六、匿名类
- 没有显式地声明一个类中的子类【肯定是个内部类】,而又想用它的子类来创建一个对象,那就可以创建为一个匿名类
- 没有类名,所以没有构造函数,会直接用其所在父类的构造方法
- 匿名类肯定会立即实现,立即使用
- 如果匿名类实现的是接口,肯定会立即回调
- 允许直接使用接口名和一个类体创建一个匿名对象
十七、异常类
- 自定义异常类
- 用throw在方法体内抛出异常
- 用throws在方法头抛出异常
十八、面向对象的设计原则
1 类之间的关系
- 泛化关系,即继承关系
- 关联关系,A类中的成中变量是用B类(接口)来声明的,即A关联于B;这是数据级的
- 依赖关系,A类中的某个方法的参数引用了B类(接口),或是返回类型是B类(接口),即A依赖于B; 这是方法级的
- 实现关系,A类实现了接口B
2 少用继承
- 子类从父类继承,是编译时就确定下来了,运行期间无法改变
- 子类和父类的关系是强耦合,父类方法的改变必然导致子类发生变化
- 继承肯定要见代码,是白盒级的
3 多用组合
- Has-A关联关系
- 这是黑盒级复用
- 弱耦合关系
- 当前对象可以在运行时动态地指定所包含的对象
- 组合的缺点:
– 对象过多
– 接口一定要定义明确