
java notes
Java丢弃了C++中很少使用的、很难理解的、令人迷惑的那些特性,如操作符重载、多继承、自动的强制类型转换。
Java语言不使用指针,而是引用。并提供了自动的废料收集。
Java语言提供类、接口和继承等面向对象的特性,为了简单起见,只支持类之间的单继承,但支持接口之间的多继承,并支持类与接口之间的实现机制(关键字为implements)。
在基本的Java应用编程接口中有一个网络应用编程接口(java net),它提供了用于网络应用编程的类库,包括URL、URLConnection、Socket、ServerSocket等。Java的RMI(远程方法激活)机制也是开发分布式应用的重要手段。
Java的强类型机制、异常处理、垃圾的自动收集等是Java程序健壮性的重要保证。
Java编译器是用Java实现的,Java的运行环境是用ANSI C实现的。
Java平台中的Java解释器对这些字节码进行解释执行,执行过程中需要的类在联接阶段被载入到运行环境中。
线程是一种特殊的对象,它必须由Thread类或其子(孙)类来创建。通常有两种方法来创建线程:其一,使用型构为Thread(Runnable)的构造子将一个实现了Runnable接口的对象包装成一个线程,其二,从Thread类派生出子类并重写run方法,使用该子类创建的对象即为线程。值得注意的是Thread类已经实现了Runnable接口,因此,任何一个线程均有它的run方法,而run方法中包含了线程所要运行的代码。线程的活动由一组方法来控制。Java语言支持多个线程的同时执行,并提供多线程之间的同步机制(关键字为synchronized)。
代码风格
- 类名:对于所有的类来说,类名的首字母应该大写。如果类名由若干单词组成,那么每个单词的首字母应该大写,例如 MyFirstJavaClass 。
- 方法名:所有的方法名都应该以小写字母开头。如果方法名含有若干单词,则后面的每个单词首字母大写。
- 源文件名:源文件名必须和类名相同。当保存文件的时候,你应该使用类名作为文件名保存(切记Java是大小写敏感的),文件名的后缀为.java。(如果文件名和类名不相同则会导致编译错误)。
- 主方法入口:所有的Java 程序由**public static void main(String []args)**方法开始执行。
所有的标识符都应该以字母(A-Z或者a-z),美元符($)、或者下划线(_)开始
合法标识符举例:age、$salary、_value、__1_value
非法标识符举例:123abc、-salary
数组是储存在堆上的对象,可以保存多个同类型变量。
Java 对象和类
- 类是对象的模板,对象是类的实例。
- 局部变量:在方法、构造方法或者语句块中定义的变量被称为局部变量。变量声明和初始化都是在方法中,方法结束后,变量就会自动销毁。局部变量是在栈上分配的。局部变量没有默认值,所以局部变量被声明后,必须经过初始化,才可以使用。访问修饰符不能用于局部变量;
- 成员变量:成员变量是定义在类中,方法体之外的变量。这种变量在创建对象的时候实例化。成员变量可以被类中方法、构造方法和特定类的语句块访问。实例变量具有默认值。数值型变量的默认值是0,布尔型变量的默认值是false,引用类型变量的默认值是null。变量的值可以在声明时指定,也可以在构造方法中指定;堆中存储。
- 类变量、静态变量:类变量也声明在类中,方法体之外,但必须声明为static类型。无论一个类创建了多少个对象,类只拥有类变量的一份拷贝。静态变量在程序开始时创建,在程序结束时销毁。大多数静态变量声明为public类型。
- 构造方法:构造方法的名称必须与类同名,一个类可以有多个构造方法。
- 声明:声明一个对象,包括对象名称和对象类型。
- 实例化:使用关键字new来创建一个对象。
- 初始化:使用new创建对象时,会调用构造方法初始化对象。
- 如果一个类定义在某个包中,那么package语句应该在源文件的首行。
- 如果源文件包含import语句,那么应该放在package语句和类定义之间。如果没有package语句,那么import语句应该在源文件中最前面。
Java包
- 包主要用来对类和接口进行分类。
数据类型
内置数据类型
- byte:byte 数据类型是8位、有符号的,以二进制补码表示的整数
- 最小值是 -128(-2^7);
- 最大值是 127(2^7-1);
- 默认值是 0;
- byte 类型用在大型数组中节约空间,主要代替整数,因为 byte 变量占用的空间只有 int 类型的四分之一;
- 例子:byte a = 100,byte b = -50。
- short:
- short 数据类型是 16 位、有符号的以二进制补码表示的整数
- 最小值是 -32768(-2^15);Short.MIN_VALUE
- 最大值是 32767(2^15 - 1);
- Short 数据类型也可以像 byte 那样节省空间。一个short变量是int型变量所占空间的二分之一;
- 默认值是 0;
- 例子:short s = 1000,short r = -20000
- int:
- int 数据类型是32位、有符号的以二进制补码表示的整数;
- 最小值是 -2,147,483,648(-2^31);Integer.MIN_VALUE
- 最大值是 2,147,483,647(2^31 - 1);
- 一般地整型变量默认为 int 类型;
- 默认值是 0 ;
- 例子:int a = 100000, int b = -200000。
- Long
- long 数据类型是 64 位、有符号的以二进制补码表示的整数;
- 最小值是 -9,223,372,036,854,775,808(-2^63);
- 最大值是 9,223,372,036,854,775,807(2^63 -1);
- 这种类型主要使用在需要比较大整数的系统上;
- 默认值是 0L;
- 例子: long a = 100000L,Long b = -200000L。
“L”理论上不分大小写,但是若写成”l”容易与数字”1”混淆,不容易分辩。所以最好大写。
- float
- float 数据类型是单精度、32位、符合IEEE 754标准的浮点数;
- float 在储存大型浮点数组的时候可节省内存空间;
- 默认值是 0.0f;
- 浮点数不能用来表示精确的值,如货币;
- 例子:float f1 = 234.5f。
- double
- double 数据类型是双精度、64 位、符合IEEE 754标准的浮点数;
- 浮点数的默认类型为double类型;
- double类型同样不能表示精确的值,如货币;
- 默认值是 0.0d;
- 例子:double d1 = 123.4。
- boolean
- boolean数据类型表示一位的信息;
- 只有两个取值:true 和 false;
- 这种类型只作为一种标志来记录 true/false 情况;
- 默认值是 false;
- 例子:boolean one = true。
- char
- char类型是一个单一的 16 位 Unicode 字符;
- 最小值是 \u0000(即为0);Character.MIN_SIZE
- 最大值是 \uffff(即为65,535);
- char 数据类型可以储存任何字符;
- 例子:char letter = ‘A’;。
- byte:byte 数据类型是8位、有符号的,以二进制补码表示的整数
引用变量
- 指向对象的变量是引用变量
- 对象、数组都是引用数据类型
- 所有引用类型的默认值都是null
- 一个引用变量可以用来引用任何与之兼容的类型。
- Dog myDog = new Dog(“hey”);
常量
final修饰
通常使用大写字母表示常量
final double PI = 3.1415;
```java
int decimal = 100;
int octal = 0144;
int hexa = 0x64;1
2
3
4
5
* 自动类型转换
* ```java
byte,short,char—> int —> long—> float —> double浮点数到整数的转换是通过舍弃小数得到 (int) -45.6f == -45
访问控制修饰符
default (即缺省,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
public : 对所有类可见。使用对象:类、接口、变量、方法
protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
修饰符 当前类 同一包内 子孙类 其他包 public
Y Y Y Y protected
Y Y Y N default
Y Y N N private
Y N N N 父类中声明为 public 的方法在子类中也必须为 public。
父类中声明为 protected 的方法在子类中要么声明为 protected,要么声明为 public,不能声明为 private。
父类中声明为 private 的方法,不能够被继承。
final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。类中的 final 方法可以被子类继承,但是不能被子类修改。
abstract 修饰符,用来创建抽象类和抽象方法,抽象类不能用来实例化对象,声明抽象类的唯一目的是为了将来对该类进行扩充。一个类不能同时被 abstract 和 final 修饰。如果一个类包含抽象方法,那么该类一定要声明为抽象类。抽象方法不能被声明成 final 和 static。
1
2
3
4
5
6
7
8
9
10public abstract class SuperClass{
abstract void m(); //抽象方法
}
class SubClass extends SuperClass{
//实现抽象方法
void m(){
.........
}
}
synchronized 和 volatile 修饰符,主要用于线程的编程。synchronized 关键字声明的方法同一时间只能被一个线程访问。synchronized 修饰符可以应用于四个访问修饰符。
transient:
- 序列化的对象包含被 transient 修饰的实例变量时,java 虚拟机(JVM)跳过该特定的变量。
volatile:
- volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14public class MyRunnalbe implements Runnable {
private volatile boolean active;
public void run(){
while(active){
// do something
}
}
public void stop(){
active = false;
}
}
// 这样的话,当两个线程一个调用run()方法时,一个调用stop时
// 在没有被volatile修饰的情况下,第一个run不会终止
// 但是在加上volatile修饰后,有一个调用stop,其他线程都会停止
transient
当对象被序列化时(写入字节序列到目标文件)时,transient阻止实例中那些用此关键字声明的变量持久化;当对象被反序列化时(从源文件读取字节序列进行重构),这样的实例变量值不会被持久化和恢复。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
//定义一个需要序列化的类
class People implements Serializable{
String name; //姓名
transient Integer age; //年龄
public People(String name,int age){
this.name = name;
this.age = age;
}
public String toString(){
return "姓名 = "+name+" ,年龄 = "+age;
}
}
public class TransientPeople {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
People a = new People("李雷",30);
System.out.println(a); //打印对象的值
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("d://people.txt"));
os.writeObject(a);//写入文件(序列化)
os.close();
ObjectInputStream is = new ObjectInputStream(new FileInputStream("d://people.txt"));
a = (People)is.readObject();//将文件数据转换为对象(反序列化)
System.out.println(a); // 年龄 数据未定义
is.close();
}
}运行结果如下:
1
2姓名 = 李雷 ,年龄 = 30
姓名 = 李雷 ,年龄 = nullvolatile
volatile可以用在任何变量前面,但不能用于final变量前面,因为final型的变量是禁止修改的。
使用的场景之一,单例模式中采用DCL双锁检测(double checked locking)机制,在多线程访问的情况下,可使用volatitle修改,保证多线程下的可见性。缺点是性能有损失,因此单线程情况下不必用此修饰符。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Singleton{
private volatile static Singleton instance = null;
private Singleton() {
}
public static Singleton getInstance() {
if(instance==null) {
synchronized (Singleton.class) {
if(instance==null)
instance = new Singleton();
}
}
return instance;
}
}