2

我有以下两段代码:

/**
 * 
 */
package com.akshu.multithreading;

/**
 * @author akshu
 *
 */
public class MyThread extends Thread {
    protected  int b;   

    private int a;
    @Override
    public void run() {

        super.run();

        System.out.println("int a:"+a);
    }

}



-----------


package com.akshu.utility;

import com.akshu.multithreading.MyThread;

public class MyUtility extends MyThread{

    public static void main(String args[])
    {
        MyThread th1 = new MyThread();
        int d =th1.b;  // line1
        System.out.println("int d"+d);
    }

}

通过上面的代码文件,我试图了解受保护的访问修饰符的目的。在文件 MyUtility 中,我试图引用 MyThread 类的变量 b。但它给了我以下错误:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
    The field MyThread.b is not visibilty.

我担心变量 b 应该可以从子类访问,因为我已经扩展了 Mythread。但它给了我编译时错误。此外,当我在我的超类中将此变量声明为静态时,我能够直接访问它。那么当我尝试通过实例访问时,我做错了什么?

4

4 回答 4

2

您无法从实例访问受保护的属性。您只能在继承类中访问它们。在这一行——

MyThread  th1  = new MyThread (); int  d  = th1 . b ;

您实际上是在尝试从实例访问受保护的属性 th1

于 2013-03-17T14:06:02.560 回答
2

方法 main 不是 MyThread 的明确部分 - 如果您要实现另一个函数,例如 prtintB(),您可以使用带有“.”的直接访问。操作员。要从 main 访问它,您必须编写一个 getter 函数。

于 2013-03-17T14:07:33.400 回答
2

来自Kathy Sierra 的巨著,解释了对protected范围的误解:

但是对于包外的子类可以访问超类(父)成员意味着什么?这意味着子类继承了成员。但是,这并不意味着包外的子类可以使用对超类实例的引用来访问该成员。换句话说,受保护=继承。受保护并不意味着子类可以将受保护的超类成员视为公共的。因此,如果 subclass-outside-the-package 获得了对超类的引用(例如,通过在子类的代码中的某处创建超类的实例),则子类不能使用超类引用上的点运算符来访问受保护的成员。对于包外的子类,受保护的成员也可能是默认的(甚至是私有的),子类只能通过继承看到受保护的成员。

因此,在您的情况下,您尝试使用引用来访问父类包之外的受保护成员:

MyThread th1 = new MyThread();
int d =th1.b;  //b cannot be reached !
于 2013-03-17T14:09:59.710 回答
1

Java 语言规范第 6.6.2.1 节将告诉你真相:

如果访问是通过字段访问表达式E.Id,whereE是 Primary 表达式,或通过方法调用表达式E.Id(. . .),whereE是 Primary 表达式,则当且仅当类型EisS或 的子类时,才允许访问S

这里MyThreadCMyUtilityS,b 是Id。因此,在 MyUtility iontance 中,您不能使用对实例 pf 的引用MyThread来访问其b

于 2013-03-17T16:16:26.677 回答