12

通常,方法的默认访问级别是本地包。但在我看来,公共抽象类是不同的。在这些类中,默认值似乎是公开的。这个对吗?

更新

@EJP

这是我的代码中的一个错误。可以用公共方法隐藏包本地方法,这让我感到困惑。这让我认为公共抽象可能类似于方法是公共的接口。请参阅示例:

a/A.java:

package a;

public abstract class A
{
    String a () { return "a"; }
}

test_a.java:

class test_a
{
    static class NewA extends a.A
    {
        public String a () { return "new a"; }
    }

    public static void main (String[] args)
    {
        NewA a = new NewA();
        System.out.println(a.a());
    }
}
4

7 回答 7

12

False,让我们看一个简单的例子:

package apackage;

public abstract class AbstractFoo {

  //A method with default visibility
  abstract void bar();

}

快速实施:

public class Foo extends AbstractFoo {

  @Override
  void bar() {}
}

现在,在另一个包中:

public static void main(String[] args) throws Exception{

  AbstractFoo something=new Foo();
  something.bar();//Compiler complains here

编译器抱怨可见性。所以方法的默认可见性是包保护的,即使类是public abstract.

于 2013-06-21T09:58:14.847 回答
4

Java 7的Java 语言规范没有提及抽象方法的单独规则,因为这种没有限定访问级别的抽象方法是默认的,也就是包私有,就像普通方法一样。

另见6.6.1。确定可访问性

  • 引用(类、接口或数组)类型的成员(类、接口、字段或方法)或类类型的构造函数只有在类型可访问并且声明成员或构造函数允许访问时才可访问:

    • 如果成员或构造函数声明为 public,则允许访问。
      接口的所有成员都是隐式公共的。
    • 否则,如果成员或构造函数被声明为受保护,则仅当满足以下条件之一时才允许访问:
      • 对成员或构造函数的访问发生在包含声明受保护成员或构造函数的类的包内。
      • 访问是正确的,如 §6.6.2 中所述。
    • 否则,如果成员或构造函数被声明为私有,则当且仅当它出现在包含成员或构造函数声明的顶级类(第 7.6 节)的主体内时,才允许访问。
    • 否则,我们说有默认访问,只有当访问发生在声明类型的包内时才被允许。

(强调我的)

另请注意,术语“默认访问”等同于“包私有”,唯一的“例外”是接口中的方法声明,它们总是public如此,因此不需要前缀。

编辑:

正如 adenoyelle 在他的回答中指出的那样,您可以覆盖不同包中的“默认”抽象方法(根据 JLS 8.4.3.1. abstractMethods中的规则所要求),因此您可以认为它们protected是JLS 似乎没有明确说明这一点。

编辑2:

我刚刚测试了它。在不同的包中实现具有默认访问方法的抽象类是不可能的。它根本无法编译。这表明该方法具有默认(包私有)访问权限,不受保护。它还表明 8.4.3.1 实际上并不要求始终可以实现抽象方法,只是它排除了无意义的选项,例如private abstract void method()

例如编译:

package example;

public abstract class AbstractTest {
    abstract void testMethod();
}

package example.sub;

import example.AbstractTest;

public class TestImpl extends AbstractTest {
    void testMethod() {
        //implemented
    }
}

导致编译错误:

example\sub\TestImpl.java:8: error: TestImpl is not abstract and does not override abstract method testMethod() in AbstractTest
public class TestImpl extends AbstractTest {
       ^
1 error
于 2013-06-21T10:01:19.837 回答
2

默认可见性称为“包”(尽管您不能使用此关键字),这意味着可以从类所属的同一包中访问该字段。

如果您声明为公开,则无论其抽象与否,它将对所有人公开

于 2013-06-21T09:54:11.857 回答
1

默认访问修饰符意味着我们没有为类、字段、方法等显式声明访问修饰符。

没有任何访问控制修饰符声明的变量或方法可用于同一包中的任何其他类。

所以不管方法是否抽象。

于 2013-06-21T09:58:08.293 回答
0

即使抽象类具有公共访问级别,方法的访问级别仍将保持默认(仅在包中可见)。只有当子类使用公共访问修饰符覆盖该方法时,它才会在包外可见。

于 2013-06-21T10:04:21.123 回答
0

你正在做一些事情,只是有点偏离:在接口中,默认——实际上是唯一的选择——是公共的。在所有类中,默认值都是相同的,即包私有。

于 2013-06-21T10:05:46.890 回答
0

即使子类“尝试”覆盖具有“公共”访问权限的子类中的抽象类中定义的具有“默认”访问权限的方法,编译器仍然会抱怨它chap6.AbstractImpl不是抽象的,并且不会getHelp()覆盖random.AbstractLearner.

getHelp()因此,实际上编译器错误消息在这里确实具有误导性,因为除非将方法的访问说明符AbstractLearner更改为 public ,否则无法修复此问题。

package random;

public abstract class AbstractLearner {

    abstract void getHelp();

}

package chap6;

import random.AbstractLearner;

public class AbstractImpl extends AbstractLearner {

    public void getHelp() {
        System.out.println("Hello");
    }
}
于 2019-06-30T19:17:30.417 回答