内部类与访问权限的问题

ThinkCat 2010-05-29 09:56:50


package pkg1;
public interface Interface {...}

package pkg2;
import pkg1.*;
public class Base {
protected class BaseInner implements Interface{
//(1)
public BaseInner() {}
...
}
}


package pkg3;
import pkg1.*;
import pkg2.*;
public class SomeClass extends Base {
Interface getBaseInner() {
//(2)
return this.new BaseInner();
}
...
}



上述代码描述如下:在包pkg2中BaseInner为Base的内部类,并实现了包pkg1中接口Interface;包pkg3中的类SomeClass继承包pkg2中的Base,并定义了一个方法getBaseInner(),返回类BaseInner的对象,然后转型为pkg1中的接口Interface。

注意(1)处的public BaseInner() {},如果没有它,也就是使用默认构造器,那么(2)处的return this.new BaseInner();会报错,因为类BaseInner的权限protected导致了其在pkg3中不可见。

我的问题是,为什么让构造函数变成public,原本protected的类就可以被别的包所访问。我的理解是类被实例化的时候,调用的是构造函数,而这个构造函数把原本protected的权限扩大成了public。不知道大家什么看法?
...全文
227 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
ZangXT 2010-05-30
  • 打赏
  • 举报
回复
还有一点class BaseInner前面的protected是Base类内部的,因此队Base的子类可见,但是BaseInner构造器前面的protected是对BaseInner的子类可见的
ThinkCat 2010-05-30
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 buzaibeishang4617016 的回复:]
不懂,顶一下
[/Quote]多谢了
wingardium 2010-05-30
  • 打赏
  • 举报
回复
Mark下,回头看
ThinkCat 2010-05-30
  • 打赏
  • 举报
回复
谢谢大家的帮助,结帖前总结一下:

1、如果不定义构造方法,则编译器自动生成与类的访问权限相同的默认构造方法。
2、除了内部类,类的访问权限不能设置成protected或是private的。
3、我先前的代码中(1)处若不写public,则会认为构造器是protected的,也就是说构造器只能被BaseInner的子类所调用,而(2)所处的类并不是BaseInner的子类,所以会出现不可见的错误。没有理解好访问权限的意义是问题出现的关键。
ThinkCat 2010-05-30
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 dracularking 的回复:]
At the member level, you can also use the public modifier or no modifier (package-private) just as with top-level classes, and with the same meaning. For members, there are two additional access modif……
[/Quote]多谢,学习了。
ZangXT 2010-05-30
  • 打赏
  • 举报
回复
是的,可以学一下单态类设计模式
ThinkCat 2010-05-30
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 zangxt 的回复:]
引用 8 楼 bgsbati1987 的回复:
引用 4 楼 zangxt 的回复:
还有一点class BaseInner前面的protected是Base类内部的,因此队Base的子类可见,但是BaseInner构造器前面的protected是对BaseInner的子类可见的
构造器前面的访问权限控制的是什么?

控制对构造器的调用。
比如写Singleton的时候,一般将构造器私……
[/Quote]写错字了,“客户端”。
ThinkCat 2010-05-30
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 zangxt 的回复:]
引用 8 楼 bgsbati1987 的回复:
引用 4 楼 zangxt 的回复:
还有一点class BaseInner前面的protected是Base类内部的,因此队Base的子类可见,但是BaseInner构造器前面的protected是对BaseInner的子类可见的
构造器前面的访问权限控制的是什么?

控制对构造器的调用。
比如写Singleton的时候,一般将构造器私……
[/Quote]把构造器写成private是不是可以这样理解:客服端程序你自己不能实例化我提供给你的类,如果你想创建一个实例,那么就用我给你的方法(就像你写的getInstance()方法)。这样做是为了封装和隐藏代码吧,没写过项目,猜是这个意思。
ZangXT 2010-05-30
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 bgsbati1987 的回复:]
引用 4 楼 zangxt 的回复:
还有一点class BaseInner前面的protected是Base类内部的,因此队Base的子类可见,但是BaseInner构造器前面的protected是对BaseInner的子类可见的
构造器前面的访问权限控制的是什么?
[/Quote]
控制对构造器的调用。
比如写Singleton的时候,一般将构造器私有化:
public class Singleton{
private Singleton(){}
public static Singleton getInstance(){...}
}
在其他地方可以写Singleton s = Singleton.getInstance();

再举个例子,我们知道子类的构造方法肯定会首先调用父类的构造方法:

class A{
protected A(){

}
}

class B extends A{
public B(){

}
}

这个是正确的,因为父类的构造方法是protected的,子类构造方法当然可以调用。
那把protected改成private呢?

class A{
private A(){

}
}

class B extends A{
public B(){ //编译错误,因为发现不能调用父类的构造方法。

}
}

ThinkCat 2010-05-30
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 zangxt 的回复:]
还有一点class BaseInner前面的protected是Base类内部的,因此队Base的子类可见,但是BaseInner构造器前面的protected是对BaseInner的子类可见的
[/Quote]构造器前面的访问权限控制的是什么?
ThinkCat 2010-05-30
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 bzimage 的回复:]
通常一个类如果不是inner class的话,那么是不能被protected 或者 private修饰的,所以我们对一个被protected修饰的类不了解,这样一个类他的缺省构造函数是什么修饰呢,应该是protected修饰。

也就是说在
protected class BaseInner implements Interface{}
这个定义中如果我们不显式的写构造函数,那么他的缺省构……
[/Quote]内部类用protected或private修饰是为了隐藏内部类吗?
dracularking 2010-05-30
  • 打赏
  • 举报
回复
At the member level, you can also use the public modifier or no modifier (package-private) just as with top-level classes, and with the same meaning. For members, there are two additional access modifiers: private and protected. The private modifier specifies that the member can only be accessed in its own class. The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package.

的确,如ZangXT
对于成员访问修饰符protected而言,其所修饰成员除了能在它本包内被访问以外,也能在包外的其所在类的子类中被访问

因此,在包外要访问BaseInner的protected构造方法,即构造BaseInner,在BaseInner子类中访问是必要条件


ZangXT 2010-05-29
  • 打赏
  • 举报
回复
三点:
1.如果你不定义构造方法,则编译器自动生成的默认构造方法与类的访问权限相同。
比如public class Test{},默认构造方法是public Test(){};
比如class Test{},默认构造方法是Test(){}
比如class Test{
protected class Inner{}//Inner的默认构造方法是protected Inner(){}
}

2.看这个例子:

package pkg1;
public class A {
protected A(){

}
}

package pkg2;
import pkg1.A;

public class B {
public static void main(String[] args) {
A a; //定义A类型的引用是没问题的
a = new A(); //创造对象不允许,因为构造函数在这里是不允许访问的
}
}



3.你的问题关键是:没有分清类型的作用范围和构造器的作业范围。
bzimage 2010-05-29
  • 打赏
  • 举报
回复
通常一个类如果不是inner class的话,那么是不能被protected 或者 private修饰的,所以我们对一个被protected修饰的类不了解,这样一个类他的缺省构造函数是什么修饰呢,应该是protected修饰。

也就是说在
protected class BaseInner implements Interface{}
这个定义中如果我们不显式的写构造函数,那么他的缺省构造函数应该是这样的:
protected BaseInner() {}

我们可以在SomeClass中定义一个inner class 来检验:
public class SomeClass extends Base {

Interface getBaseInner() {
// return new BaseInner();
return new SomeInner();
}

protected class SomeInner extends BaseInner {
}
}
这样写是合法的。
  • 打赏
  • 举报
回复
不懂,顶一下

62,612

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧