Java中公共抽象类中方法的默认访问级别是什么?

时间:2013-06-21 09:51:59

标签: java

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

更新

@EJP

这是我的代码中的一个错误。可以使用公共方法隐藏包本地方法,这让我感到困惑。这让我觉得公共摘要可能类似于公共方法的接口。参见示例:

一个/ 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());
    }
}

7 个答案:

答案 0 :(得分:11)

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

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

答案 1 :(得分:2)

Java Language Specification for Java 7没有提到抽象方法的单独规则,因为没有合格访问级别的抽象方法是默认的包私有,就像普通方法一样。

另见6.6.1. Determining Accessibility

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

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

(强调我的)

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

修改

正如adenoyelle在his answer中指出的那样,您可以在不同的包中覆盖'默认'抽象方法(根据JLS 8.4.3.1. abstract Methods中的规则的要求),因此您可以将它们视为{ {1}},但快速扫描JLS似乎并没有明确这一点。

编辑2:

我刚试过它。在不同的包中实现具有默认访问权限的方法的抽象类是不可能的。它根本不编译。这表明该方法具有默认(包私有)访问,而不受保护。它还表明8.4.3.1实际上并不要求始终可以实现抽象方法,只是它排除了诸如protected

之类的无意义选项。

例如编译:

private abstract void method()

package example.sub;

package example;

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

导致编译错误:

import example.AbstractTest;

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

答案 2 :(得分:1)

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

如果您宣布公开,那么无论是否为摘要都是公开的

答案 3 :(得分:1)

  

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

声明没有任何访问控制修饰符的

A variable or method可用于同一包中的任何其他类。

所以这个方法无论抽象与否都没有。

答案 4 :(得分:0)

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

答案 5 :(得分:0)

你正在做点什么,只是有点偏离:在接口中,默认 - 事实上唯一的选择 - 是公开的。在所有类中,默认值都相同,即package-private。

答案 6 :(得分:0)

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

因此,实际上,这里的编译器错误消息确实令人误解,因为除非将getHelp()中的AbstractLearner方法的访问说明符更改为public,否则无法解决此问题。 / p>

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");
    }
}