Java常用关键字

abstract

final

修饰类

被final修饰的类不能被继承

final修饰对象

修饰方法

“使用final方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。在早期的Java实现版本中,会将final方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升。在最近的Java版本中,不需要使用final方法进行这些优化了。”

由此可见,被final修饰的方法最主要的目的就是防止方法被重写

修饰变量

对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。

final修饰基本类型

final修饰对象

对象的引用无法改变,但是对象的属性值可不可以改变呢?

final修饰对象

因为payStatus是int类型,初始化时候会给定默认值:0

此时输出结果

1  
10

从结果来看,final”锁定”的是对象的引用,并没有”锁定”属性的值

注意事项

final与static的区别,static作用于成员变量用来表示只保存一份副本,而final的作用是用来保证变量不可变。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
final class Father{
public final Double i = Math.random();
public static Double j = Math.random();
}

public static void main(String[] args){
Father f = new Father();
Father ff = new Father();
System.out.println(f.i);
System.out.println(f.j);
System.out.println();
System.out.println(ff.i);
System.out.println(ff.j);

}

输出结果:

0.41791403026319096  
0.8147697161273327   

0.9571817275395188  
0.8147697161273327     

参考资料

博客园-海子-浅析Java中的final关键字

博客园-五月的仓颉-谈谈final的作用

static

  1. 静态方法内部不能调用非静态方法,非静态方法没有此限制。
  2. static修饰的变量属于类变量,可以通过类名.变量名直接引用,而不需要new出一个类来
  3. static修饰的方法属于类方法,可以通过类名.方法名直接引用,而不需要new出一个类来

静态资源是类初始化的时候加载的,类实例之间共享,一处变,处处变。

并且被static修饰的方法是没有this的,他不依附于任何对象。但是非静态方法是依赖于具体对象而调用的。这就是为什么静态方法内部不能调用非静态方法。

既然静态资源不依赖于任何对象,那为什么还要放在不同对象里呢。是不是可以把所有静态资源全都放到一起?

  1. 避免重名,通过不同对象使同名静态资源区分开。
  2. 资源分类清晰,功能明确。
  3. 放到一起,那存放静态资源的这个类会特别大。

静态资源(变量/方法/代码块)

static变量也称作静态变量,静态变量和非静态变量的区别是:

静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。
而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。

很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。

注意事项

静态资源真的没有this吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
final class Father{
static int wg = 31;

public void pringtWg(){
int wg = 13;
System.out.println(this.wg);
}

}

public class TestExcel {

public static void main(String[] args) throws Exception {
new Father().pringtWg();
}

}

输出:

31

this是指当前对象,printWg中的wg是局部变量,无法与this内联。

常见面试题

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
public class Son extends Father{

static{
System.out.println("son static");
}

public Test(){
System.out.println("son constructor");
}

public static void main(String[] args) {
System.out.println("main()");
new Son();
}
}

class Father{

static{
System.out.println("father static");
}

public Base(){
System.out.println("father constructor");
}
}

输出:

father static  
son static  
main()
father constructor  
son constructor  

程序执行顺序:

  1. main()作为程序入口;
  2. 需要加载Son,发现Son继承Father,加载Father;
  3. Father中有static块,初始化加载这个static块;
  4. 返回Son,Son中有static块,初始化这个static块;
  5. 打印输出字符串”main()”
  6. 执行new Son();
  7. Son继承Father,Father有构造函数,执行构造函数;
  8. 返回Son,Son有构造函数,执行构造函数;

第2~4步是对象的加载过程,第5~7步是对象的执行过程;输出结果与执行顺序的对应关系

输出行 对应执行顺序
father static 3
son static 4
father constructor 7
son constructor 8

不难发现即使mian()中并没有语句,但仍然会有输出。就像之前所说,jvm会把所有不在方法内部的的静态资源初始化。

参考资料

博客园-海子-浅析Java中的final关键字

博客园-五月的仓颉-谈谈final的作用

包和访问权限控制关键字

package

  • 包是可以理解为命名空间,他能有效解决类重名问题。
  • 为了方便组织和管理,多用倒置域名来标识。

默认访问权限(包访问权限)、public、private和protected

一个.java文件只能有一个被public修饰的类,并且类名必须与文件名相同。如果没有public关键字,则对类的命名没有要求。

修饰类

  • 默认访问权限(包访问权限):用来修饰类的话,表示该类只对同一个包中的其他类可见。
  • public:用来修饰类的话,表示该类对其他所有的类都可见。
  • 如果你想实现其他任何人都不能访问该类,可以通过将类的所有构造器都指定为private。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    package com.qigou.b2cex.test;

    class People {

    private String name = null;

    public People(String name) {
    this.name = name;
    }

    public String getName(){
    return name;
    }
    public void setName(String name){
    this.name = name;
    }
    }
1
2
3
4
5
6
7
package com.qigou.b2cex.test;

public class TestExcel{
public static void main(String[] args) throws Exception {
System.out.println(new People("BBDog").getName());
}
}

输出结果:

BBDog

将People的包名改为test1后

默认访问权限权限

修饰方法和变量

作用域 当前类 同包下 子孙 所有类
public
protected ×
默认 × ×
private × × ×
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.qigou.b2cex.test;

public class People {

private String name = null;

public People(String name) {
this.name = name;
}

public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
}
1
2
3
4
5
6
7
8
package com.qigou.b2cex.test;

public class TestExcel{
public static void main(String[] args) throws Exception {
People people = new People("BBDog");
System.out.println(people.getName());
}
}

变更getName()的权限,每次初始化包名。

  • public

    正常输出: BBDog

  • 默认

    同包下正常输出: BBDog

    修改People包名为test1

    不同包默认权限方法

  • protected

    同包下正常输出: BBDog

    修改People包名为test1

    不同包protected

    创建Kids类继承People

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    package com.qigou.b2cex.test;

    import com.qigou.b2cex.test1.People;
    public class Kids extends People {

    public Kids(String name){
    super(name);
    }

    public String toString() {
    return getName();
    }
    }

    子类拥有权限,但是调用子类仍然不被允许

    protectedChildern

  • private

    protectedChildern

    参考资料

博客园-海子-浅析Java中的final关键字