在Java中,我们经常看到public
、protected
、private
这些修饰符。在Java中,这些修饰符可以用来限定访问作用域。
public
定义为public
的class
、interface
可以被其他任何类访问:
package abc;public class Hello { public void hi() { } }
上面的Hello
是public
,因此,可以被其他包的类访问:
package xyz;class Main { void foo() { // Main可以访问Hello Hello h = new Hello(); } }
定义为public
的field
、method
可以被其他类访问,前提是首先有访问class
的权限:
package abc;public class Hello { public void hi() { } }
上面的hi()
方法是public
,可以被其他类调用,前提是首先要能访问Hello
类:
package xyz;class Main { void foo() { Hello h = new Hello(); h.hi(); } }
private
定义为private
的field
、method
无法被其他类访问:
package abc;public class Hello { // 不能被其他类调用: private void hi() { } public void hello() { this.hi(); } }
实际上,确切地说,private
访问权限被限定在class
的内部,而且与方法声明顺序无关。推荐把private
方法放到后面,因为public
方法定义了类对外提供的功能,阅读代码的时候,应该先关注public
方法:
package abc;public class Hello { public void hello() { this.hi(); } private void hi() { } }
由于Java支持嵌套类,如果一个类内部还定义了嵌套类,那么,嵌套类拥有访问private
的权限:
// private public class Main { public static void main(String[] args) { Inner i = new Inner(); i.hi(); } // private方法: private static void hello() { System.out.println("private hello!"); } // 静态内部类: static class Inner { public void hi() { Main.hello(); } } }
定义在一个class
内部的class
称为嵌套类(nested class
),Java支持好几种嵌套类。
protected
protected
作用于继承关系。定义为protected
的字段和方法可以被子类访问,以及子类的子类:
package abc;public class Hello { // protected方法: protected void hi() { } }
上面的protected
方法可以被继承的类访问:
package xyz;class Main extends Hello { void foo() { Hello h = new Hello(); // 可以访问protected方法: h.hi(); } }
package
最后,包作用域是指一个类允许访问同一个package
的没有public
、private
修饰的class
,以及没有public
、protected
、private
修饰的字段和方法。
package abc;// package权限的类:class Hello { // package权限的方法: void hi() { } }
只要在同一个包,就可以访问package
权限的class
、field
和method
:
package abc;class Main { void foo() { // 可以访问package权限的类: Hello h = new Hello(); // 可以调用package权限的方法: h.hi(); } }
注意,包名必须完全一致,包没有父子关系,com.apache
和com.apache.abc
是不同的包。
局部变量
在方法内部定义的变量称为局部变量,局部变量作用域从变量声明处开始到对应的块结束。方法参数也是局部变量。
package abc;public class Hello { void hi(String name) { // ① String s = name.toLowerCase(); // ② int len = s.length(); // ③ if (len < 10) { // ④ int p = 10 - len; // ⑤ for (int i=0; i<10; i++) { // ⑥ System.out.println(); // ⑦ } // ⑧ } // ⑨ } // ⑩}
我们观察上面的hi()
方法代码:
方法参数name是局部变量,它的作用域是整个方法,即①~⑩;
变量s的作用域是定义处到方法结束,即②~⑩;
变量len的作用域是定义处到方法结束,即③~⑩;
变量p的作用域是定义处到if块结束,即⑤~⑨;
变量i的作用域是for循环,即⑥~⑧。
使用局部变量时,应该尽可能把局部变量的作用域缩小,尽可能延后声明局部变量。
final
Java还提供了一个final
修饰符。final
与访问权限不冲突,它有很多作用。
用final
修饰class
可以阻止被继承:
package abc;// 无法被继承:public final class Hello { private int n = 0; protected void hi(int t) { long i = t; } }
用final
修饰method
可以阻止被子类覆写:
package abc;public class Hello { // 无法被覆写: protected final void hi() { } }
用final
修饰field
可以阻止被重新赋值: