Java的关键字整理
整理一下不常见的关键字
1. enum关键字
jdk1.5时出现的关键字,用于穷举有限宽度的对象集合(比如说一个星期有且只有七天,性别有且只有男女),用法较多,这里就举个例子。
public class Demo {
public static void main(String[] args) {
Sex people = Sex.MALE; //是值,不用new XXXX,直接赋值即可
switch (people){
case MALE:
//.....
break;
case FEMAL:
//......
break;
}
}
}
//声明一个枚举,由于都是定值,所以也不需要什么构造函数了(有也可以,也可以像类一样在内部添加方法)
enum Sex{
MALE, FEMAL;
}
2. final关键字
final关键字可以用于修饰类,方法,对象,参数,特点是修饰之后不能再做改动。
-
修饰类的时候,这个类不能再被其他类继承。
-
用于修饰方法的时候,子类不允许重写(Override)这个方法。
-
用于修饰对象的时候,不能再修改值。首先区分是八大基本类型还是类
- 修饰基本类型的时候,不允许再更改它的值。
- 修饰类的时候,由于是引用,所以不允许重新引用成其他对象(简单来说就不能再次使用=运算符),但是可以修改其内部数据。
public static void main(String[] args) { final Test test = new Test(); test.string = "111"; //可以运行 test = new Test(); //编译不通过 } class Test{ public String string; }
- 在使用的时候,可以先不赋值设为空,然后在需要的时候再赋值,不过一旦赋值后不能更改是和之前一样。
public class Demo { public static void main(String[] args) { final Test test; //不报错 test = new Test(); //不报错 test.string = "111"; final int i; i = 10; //不报错 } } class Test{ public String string; }
- 修饰基本类型的时候,不允许再更改它的值。
-
修饰参数的时候,同修饰对象 ,不能再修改值。
3. finally关键字
常用于异常获取模型中(try/catch),在finally中的代码(语句块)无论是否发生异常,都一定会执行,且执行顺序在最后。
try{
String s = null;
System.out.println("try " + s.toString()); //这行不会输出,因为报错了
}catch (Exception e){
System.out.println("catch");
}finally {
System.out.println("finally");
}
catch
finally
try{
String s = "s";
System.out.println("try " + s.toString());
}catch (Exception e){
System.out.println("catch");
}finally {
System.out.println("finally");
}
try s
finally
3.1 finally和return
在try/catch语句中,如果在try或者catch代码块中有return语句,finally语句会在return之前先执行。
public static int getNum(){
try{
return 1;
}catch (Exception e){
}
finally {
return 2; //结果是返回2
}
}
4. instanceof关键字
instanceof是一个操作符,用于判断前一个对象是不是后面一个对象的实例,一般用于if的条件判断中。
用于判断传入的参数是否是某种类的实例。
public static void main(String[] args) {
Object o = new ArrayList<>();
judge(o);
}
public static void judge(Object o){
if (o instanceof ArrayList) System.out.println("true"); //这个不用多说
if (o instanceof List) System.out.println("true"); // implement的类也是true
if (o instanceof Object) System.out.println("true"); // extends的类也是true
if (!(o instanceof Date)) System.out.println("false"); // false
}
5. volatile关键字
Java支持通过使用volatile关键字的办法来进行线程通信,对于声明了volatile的对象而言,它在所有线程中的数据都会保持相等。
-
声明volatile的对象,每个线程都会相当于从主存获取这个对象的状态。
-
volatile无法保证变量的操作是原子性的,开10个线程,每个线程加1000次,大部分无法达到10000的答案。
public class NoAutoMaticTest {
public volatile int inc = 0;
public void increase() {
inc++;
}
public static void main(String[] args) {
final NoAutoMaticTest test = new NoAutoMaticTest();
//10个线程对加1000次,本应该得到10000,实际上会因为无法保证变量操作是原子性,经常达不到10000
//而如果换成synchronized或者lock都可以得到10000
for(int i=0;i<10;i++){
new Thread(){
public void run() {
for(int j=0;j<1000;j++)
test.increase();
};
}.start();
}
while(Thread.activeCount()>1) //保证前面的线程都执行完
Thread.yield();
System.out.println(test.inc);
}
}
6. default关键字
这里的default关键字不是指switch语句中的那个default,而是Java8之后才加入的,专门用于接口Interface使用的关键字,当interface中的方法使用default关键字后,可以直接实现其内部的默认功能。
public class test implements interface1{
public static void main(String[] args){
//不用实现print方法就可以直接调用
new test().print();
}
}
interface interface1{
default void print(){
System.out.println("hello default");
}
}
6.1 default冲突
当一个类同时引用两个接口,而两个接口又拥有同名的default方法时,就会报错,原因是编辑器不知道到底要引用哪一个方法。
解决方法:
- 重写这个默认实现的方法。
public class test implements interface1, interface2{ @Override public void print() { } }
- 在实现类中指明使用的接口。
public class test implements interface1, interface2{ @Override public void print() { interface1.super.print(); } }
7. Serializable关键字
在类的数据要保存到本地或者通过网络传输的时候,这个类就要实现序列化,具体就是implements Serializable。
public class SeriesTest implements Serializable {
private String name;
private String id;
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
}
然后序列化用ObjectOutputStream,反序列化用ObjectInputStream。
public class test {
public static void main(String[] args) {
//in();
out();
}
public static void in(){
// 实例化一个对象
SeriesTest seriesTest = new SeriesTest();
seriesTest.setId("11");
seriesTest.setName("name");
try{
FileOutputStream fileOut = new FileOutputStream("/tmp/test.txt");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
// 写入数据
out.writeObject(seriesTest);
out.close();
fileOut.close();
System.out.printf("Serialized data is saved in /tmp/test.txt");
}catch (Exception e){
e.printStackTrace();
}
}
public static void out(){
SeriesTest seriesTest = null;
try
{
FileInputStream fileIn = new FileInputStream("/tmp/test.txt");
ObjectInputStream in = new ObjectInputStream(fileIn);
// 读取数据
seriesTest = (SeriesTest)in.readObject();
in.close();
fileIn.close();
}catch(IOException i)
{
i.printStackTrace();
return;
}catch(ClassNotFoundException c)
{
c.printStackTrace();
return;
}
System.out.println("Name: " + seriesTest.getName());
System.out.println("Id: " + seriesTest.getId());
}
}
运行in:
Serialized data is saved in /tmp/test.txt
运行out:
Name: name
Id: 11
7.1 transient
被transient声明的成员变量不参与序列化。
public class SeriesTest implements Serializable {
private String name;
private transient String id; // 将 id 用transient声明
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
}
运行in:
Serialized data is saved in /tmp/test.txt
运行out:
Name: name
Id: null