<Java SE 详解> Java访问控制符-
1、访问修饰符(access modifier)
public(公共的):被public所修饰的属性和方法可以被外界任何类直接访问。
protected(受保护的):被protected所修饰的属性和方法 可以在1类内部、2相同包、以及3该类的子孙类可以访问。
例:
C类:
package cn.edu.bupt.common;
public class C {
protected int year = 2010;
}
D类:
package cn.edu.bupt;
import cn.edu.bupt.common.C;
public class D extends C {
public static void main(String[] args) {
D d = new D(); //声明D的实例对象,而不是C的实例对象
System.out.println(d.year);
}
}
----------------------------------------------------------------------
注意:这里所指的子孙类可访问父类protected成员并不是对应下例,注意理解 二十七-21:00
C类:
package cn.edu.bupt.common;
public class C {
protected int year = 2010;
}
D类:
package cn.edu.bupt;
import cn.edu.bupt.common.C;
public class D extends C {
public static void main(String[] args) {
C c = new C();
System.out.println(c.year); //compiling error
}
}
解释:根据《Java核心技术》 P160 解释说:
Manger类(子类)中的方法只能够访问Manager对象中的hireDay域(protected类型,从Empoyee中继承过来),而不能直接访问其他Employee(父类)对象中的这个域。这种限制是有助于避免滥用受保护机制,使得子类只能在其内部获得访问受保护域的权利。
换句话说,实质上,这里的D类还是需要访问自身继承过来的protected成员变量(继承过来),而不能直接通过父类引用(哪怕是父类的引用指向了子类的实例对象)访问其父类所生成对象的protected成员变量。
在同一个包下面,一个类的protected成员可以直接在另一个类中通过“对象.protected成员名”访问。同default类型。
但是当protected成员被子类继承后,继承下来的成员在子类中充当private成员的角色,此时这种继承过来的protected成员是不能被子类所在包中的其他类访问的;但是,这种子类中的protected成员还可以继续被再下面的子孙类访问,但同样不能再被同包中的其他类直接访问。
再一例:
package cn.edu.bupt.common;
import cn.edu.bupt.C;
public class D extends C {
private int count;
//-----------constructor-------------
public D(int count) {
super();
this.count = count;
}
//------------------------------------
public void output(D dparam) {
C c = dparam;
System.out.println(c.year); //compiling error
D d = (D)c;
System.out.println(d.year);
}
public static void main(String[] args) {
D d = new D(2008);
d.output(d);
}
}
总结:上例说明,对于任何一个类,不管是子类还是父类,他们都是一个单独的个体,仅仅能访问自身原生定义成员(不管是不是private类型)、或者是从父类中继承过来的可在子类中访问的protected类型(不包括父类中private和default类型,因为它们不能被继承),对于动态成员的访问形式,可以
<1>通过this关键字在类的定义空间范围当中进行访问(“对象.成员”形式);
<2>当然可以在类中new任何当前类的实例对象(同样是“对象.成员”形式);
<3>还可以通过外界传递进入类内部当前类的另一个实例对象的引用
来访问另一个同类对象内部任何的成员(只要当前对象能访问到的成员均可,包括private类型成员,但是不包括父类中的private和default成员),唯一条件是在只要在目标类的内部均可进行访问,包括private类型成员。
在例如String类的equals()函数实现方法:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject; //只要转换为本类对象即可访问内部的private成员,而且编译不会发生错误
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
但是,在子类的内部是不能按照上面之处的后两种方式通过父类型的引用(即使它指向的当前类的对象)去访问父类对象中的不可访问成员(如private和protected成员),这样会产.生编译错误,因为子类和父类所指对象不是同类对象。如上例中所示。
default(不加任何访问修饰符):在本类内部,以及同一个包下面的类可访问。
private(私有的):被private所修饰的属性和方法仅限于在定义了该属性或方法的类的内部(类所在代码的内部)使用。类的内部意思是,只要是类的内部,不管是内部初始化语句、实例方法还是静态方法,只要在类的内部均可以访问private成员。
例:
package cn.edu.bupt.designpattern;
public class PrivateSingle {
private PrivateSingle() {
System.out.println("private constructor invoked");
}
public static void main(String[] args) {
Object o = new PrivateSingle();
}
}
2、在这里发现一些误区:
1> 误区:“对于private成员,是不可以通过“对象名.私有成员名”形式进行访问的”; ×
正解:对于任何类型的实例成员均可以通过“对象名.成员名”形式进行访问的,只不过需要注意根据访问修饰符来确定使用这种形式进行访问的环境,如果环境恰当则不会发生编译错误。
例:
package cn.edu.bupt.common;
public class C {
private int year = 2010;
public static void main(String[] args) {
C c = new C();
System.out.println(c.year); //因为main方法是在C类的内部,因此可以直接通过"对象名.私有成员名"进行访问
}
}
3、访问修饰符与继承之间的关系: 二十七-27:00
public:可以被任何类访问,包括自己和子类和外界类;
protected:可以被自己访问、子类继承访问(子类内部直接访问)、以及相同包中的其他类所访问(通过生成该类对象以及“对象.protected成员变量名”进行访问);
default:可以被自己内部访问、相同包中的其他类所访问(通过生成该类对象以及“对象.protected成员变量名”进行访问),但是子类是不能访问并继承这种类型的成员(已经测试);
例:
C.java
package cn.edu.bupt.common;
public class C {
int year = 2010;
}
D.java
package cn.edu.bupt;
import cn.edu.bupt.common.C;
public class D extends C {
public static void main(String[] args) {
D d = new D();
System.out.println(d.year); //compiling error
}
}
private:仅仅被自己内部访问。
注意default和protected黄色区域。
4、instanceof关键字:判断某个对象是否是某个类的实例。
语法形式:引用名 instanceof 类名(或抽象类名或接口名) 返回boolean值。间接反映了多态
例:
public class InstanceTest
{
public static void main(String[] args)
{
People p = new Man();
System.out.println(p instanceof People); //print true
}
}
class People
{
}
class Man extends People
{
}
说明:这里返回true是因为People类型的引用变量p所指的对象是Man类型的实例,即子类实例。而对于多态,子类对象就是父类实例,Man是People,因此Man对象就是People类型的一个实例,因此,返回true。 二十七-35:00
Man是People的子类,根据继承,子类就是父类,因此Man可以看做是People的实例。
浙公网安备 33010602011771号