Java基础概述
序
工作流程
程序结构
public class Dog {
public static void main(String[] args) {
statement1; //语句
} //方法
} //类
基本语法:
- 大小写敏感
- 类名的首字母应大写,方法名的首字母应小写
- 变量名必须以**字母、下划线或$**开头
- 所有的 Java 程序由 public static void main(String[] args) 方法开始执行
源文件声明规则:
- 一个源文件中只能有一个 public 类,可以有多个非public类
- 源文件名须和public类名相同
- 如果一个类定义在某个包中,那么package语句应该在源文件的首行
- 如果源文件包含import语句,那么应该放在package语句和类定义之间;如果没有package语句,那么应该放在最前面
- import语句和package语句对源文件中定义的所有类都有效。在同一源文件中,不能给不同的类不同的包声明
类和对象
**所有的Java程序都定义在类中,类是对象的蓝图。**对象是类的一个实例,包含实例变量(状态)和方法(行为)。
变量
primitive主数据类型
类型 | 位数 | 值域 |
---|---|---|
boolean | (JVM决定) | true/false |
char | 16 bits | 0~65535 |
byte | 8 bits | -128~127 |
short | 16 bits | -32768~32767 |
int | 32 bits | -2147483648~2147483647 |
long | 64 bits | -9,223,372,036,854,775,808~9,223,372,036,854,775,807 |
float | 32 bits | 范围规模可变 |
double | 64 bits | 范围规模可变 |
注:
float f = 32.5f 除非加上f,否则所有带小数点的值都会被 Java 当作 double 处理
对象引用
1. 声明一个引用变量
Dog myDog //要求Java虚拟机分配空间给引用变量,并将此变量命名为myDog
2. 创建对象
new Dog() //要求Java虚拟机分配堆空间给新建的Dog对象
3. 连接对象和引用
Dog myDog = new Dog(); //将Dog对象赋值给myDog
对象引用变量保存的是存取对象的方法。它并不是对象的容器,而是类似指向对象的指针。
Dog kuma = new Dog();
Dog kai = new Dog(); //引用数:2 对象数:2
Dog hank = kuma; //引用数:3 对象数:2
kai = kuma; //引用数:3 对象数:1
kai = null; //作用中的引用数:2 null引用数:1 对象数:1
实例变量 vs 局部变量
- 实例变量声明在类中,而局部变量声明在方法中
- 实例变量有默认值,而局部变量没有(即在使用前必须初始化)
- 局部变量是在栈上分配的
静态变量(类变量)
- 类变量也称为静态变量,在类中以 static 关键字声明,但必须在方法之外。
- 无论一个类创建了多少个对象,类只拥有类变量的一份拷贝。
- 静态变量除了被声明为常量外很少使用,静态变量是指声明为 public/private,final 和 static 类型的变量。静态变量初始化后不可改变。
- 静态变量储存在静态存储区。经常被声明为常量,很少单独使用 static 声明变量。
- 静态变量在第一次被访问时创建,在程序结束时销毁。
- 默认值和实例变量相似。数值型变量默认值是 0,布尔型默认值是 false,引用类型默认值是 null。变量的值可以在声明的时候指定,也可以在构造方法中指定。此外,静态变量还可以在静态语句块中初始化。
- 静态变量可以通过:ClassName.VariableName的方式访问。
- 类变量被声明为 public static final 类型时,类变量名称一般建议使用大写字母(代表常量)。如果静态变量不是 public 和 final 类型,其命名方式与实例变量以及局部变量的命名方式一致。
- 静态变量会在该类的任何对象创建之前就完成初始化。
- 静态变量会在该类的任何静态方法执行之前就初始化。
class Player {
static int playerCount = 0;
private String name;
public Player(String n) {
name = n;
playerCount++;
}
}
public class PlayerTestDrive {
public static void main(String[] args) {
System.out.println(Player.playerCount); //0
Player one = new Player("Tiger Woods");
System.out.println(Player.playerCount); //1
}
}
方法
修饰符 返回值类型 方法名(参数类型 参数名) {
...
方法体
...
return 返回值;
}
Java是通过值传递的,也就是说通过拷贝传递(实参、形参)
Java注重类型:可以返回会被隐含转换成声明类型的其他类型值,但若声明的类型容器小于想要返回的类型时必须作明确的转换。实参变量容器可小于形参变量,指派变量容器须大于等于返回值类型容器。
封装
基本原则:将实例变量标记为private,并提供public的getter与setter来控制存取动作。
public class Person{
private String name;
private int age;
public int getAge(){
return age;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age = age;
}
public void setName(String name){
this.name = name;
}
} //this关键字是为了解决实例变量和局部变量之间的同名冲突
构造函数
构造函数带有初始化对象时会执行的程序代码,唯一能够调用构造函数的办法就是新建一个类。它会在对象能够被赋值给引用之前就执行。在创建新对象时,所有继承下来的构造函数都会执行。
要求:
- 构造函数必须与类同名且没有返回类型
- 如果已经存在一个有参数的构造函数,且需要一个无参数的构造函数,则必须手动声明(编译器不会自动生成)
- 如果类有一个以上的构造函数,则其参数必须不同(顺序或类型)
- 使用this()可从某个构造函数调用同一个类的其他构造函数,this()只能用在构造函数中,且必须是第一行语句
- super()和this()不能兼得
class Mini extends Car {
Color color;
public Mini() {
this(Color.Red);
} //调用带参数的构造函数
public Mini(Color c) {
super("Mini"); //调用父类构造函数
color = c;
//初始化动作
}
}
静态方法
静态的方法不能调用非静态的变量和非静态的方法。
可变参数
JDK1.5 开始,Java支持传递同类型的可变参数给一个方法:typeName… parameterName。
一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。
继承与多态
继承
如果类Y继承于类X,且类Y是类Z的父类,那么Z应该能通过IS-A X的测试。
父类可以通过存取权限决定子类是否能够继承某些特定的成员:private < default < protected < public。子类会继承父类所有public类型的实例变量和方法,但不会继承父类所有private类型的变量和方法;继承得到的方法可以被覆盖,但实例变量不能被覆盖;当某个方法在子类中被覆盖,调用此方法时会使用覆盖过的版本。
public void roam() {
super.roam(); //调用父类的roam()
//my own roam stuff
} //扩充
Java 的继承是单继承,但是可以多重继承。单继承就是一个子类只能继承一个父类,多重继承就是,例如 B 类继承 A 类,C 类继承 B 类,所以按照关系就是 B 类是 C 类的父类,A 类是 B 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
防止某个类被继承
- 存取控制 尽管类不能被标记为私有,但可以不标记公有。非公有的类只能被同一个包的类作出子类。
- final修饰符 表示它是继承树的末端,不能被继承。
- 让类只拥有private的构造函数。
多态
多态是同一个行为具有多个不同表现形式或形态的能力。
实现方式
-
重载和重写
方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
-
接口
-
抽象类和抽象方法
重写(override)
- 参数必须一样,且返回类型必须是父类返回值的派生类
- 不能降低方法的存取权限
- 子类和父类在同一个包中,那么子类可以重写父类除private和final的所有方法;子类和父类不在同一个包中,那么子类只能重写父类public和protected的非final方法
- 构造方法不能被重写
- 重写的方法能够抛出任何非强制异常,但不能抛出新的强制性异常
重载(overload)
- 必须改变参数列表
- 可以改变返回类型
- 可以更改存取权限
- 可以声明新的或更广泛的检查异常
- 方法能够在同一个类中或者在一个子类中被重载
public class Overloads {
String uniqueID;
public int addNums(int a, int b) {
return a+b;
}
public double addNums(double a, double b) {
return a+b;
}
public void setUniqueID(String theID) {
...
uniqueID = theID;
}
public void setUniqueID(int ssNumber) {
String numString = "" + ssNumber;
setUniqueID(numString);
}
} //examples
接口
[可见度] interface 接口名称 [extends 其他的接口名] {
// 声明变量
// 抽象方法
}
接口有以下特性:
-
接口是隐式抽象的,声明接口时不必使用abstract关键字
-
接口中每一个方法也是隐式抽象的,声明时同样不需要abstract关键字
-
接口中的方法都是公有的
-
多重继承
抽象类和抽象方法
抽象类除了被继承过之外,是没有用途、没有值、没有目的的。它不能实例化对象,但可以作为引用类型。
抽象的方法没有实体,代表此方法一定要被覆盖过,其意义是可以定义出一组子型共同的协议。
抽象类可以带有抽象和非抽象的方法,但不能在非抽象类中定义抽象方法。
public abstract class Employee
{
private String name;
private String address;
private int number;
public abstract double computePay();
//其余代码
}
public class Salary extends Employee
{
private double salary; // Annual salary
public double computePay()
{
System.out.println("Computing salary pay for " + getName());
return salary/52;
}
//其余代码
}
注:
- 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
- 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。
异常处理
分类
- **检查性异常:**最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
- 运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
- 错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
流程控制
try {
...
}catch(Exception ex) {
...
}finally {
...
}
...
try执行失败 抛出异常,执行catch块代码,完成后执行finally块
try执行成功 跳过catach块,执行finally块
若try或catch块有return指令,流程会跳到finally执行再回到return指令
规则
- catch与finally不能没有try
- try与catch之间不能有程序
- try一定要有catch或finally
- 只带有finally的try必须要声明异常
void go() throws FooException {
try {
x.doStuff();
}finally{ }
}
多重异常
异常是多态的,有多个catch块时要从小排到大。