【问题标题】:Java: Private Inner Classes being returned to external codeJava:将私有内部类返回给外部代码
【发布时间】:2012-06-10 23:15:09
【问题描述】:

我最近刚开始学习 Java,来自 C# 背景。

当我开始使用 Collections 时,我注意到 Arrays.asList() 返回一个 ArrayList<T> 对象。

然而,我不明白的是,根据“docjar”(第 2834 行)的代码清单,将 ArrayList<T> 标记为 private

如何使用已明确标记为对我隐藏的对象?或者(这是我怀疑的),private 是否与我假设的含义不同?

(另外,我注意到该类被标记为静态,这也让我感到困惑,但我将在单独的问题中提出)


编辑:引发编译器错误的 C# 示例:

public class PubClass {
        private class Blah {

        }

        public Blah GetBlah() {
            return new Blah();
        }
}

给出:可访问性不一致:返回类型“Namespace.PubClass.Blah”比方法“Namespace.PubClass.GetBlah()”更难访问

【问题讨论】:

  • 它是私有的,是的,但是一旦从方法中返回,它就可以随心所欲,就像任何“getter”方法一样。
  • 但是如果它是私有的,我该如何使用它的方法和字段呢?这不是破坏安全吗?或者,换一种说法:将其标记为私有有什么意义? (如果你明白我的意思)
  • 不,您将引用变量的可见性与引用或对象本身混淆了。虽然引用变量是并且将始终是私有的,但对象或引用本身并不关心或知道这一点。如果它是从方法返回的,则可以使用它。这与 C# 没有什么不同。引用既不是私有的,也不是公开的。只有变量可以是其中之一。
  • 我认为私有 ArrayList 类的存在主要是为了允许序列号。
  • @HovercraftFullOfEels 它还存在以允许 RandomAccess 标志到位。

标签: java list private internal


【解决方案1】:

返回给您的ArrayList 实现List 以及该接口中包含的所有方法。由于List 是公开的,因此您知道这些方法并可以调用它们。

ArrayList 之所以是私有的,是因为它没有理由公开:它不提供除 List 接口提供的功能之外的任何其他功能。

/编辑
你的例子没有模仿这里发生的事情:

public interface List<T> {
    /** snip */
}

public class Arrays {
    private static class ArrayList<T> implements List<T> {
        /** snip */
    }

    public <T> List<T> asList(T... arr) {
        return new ArrayList<>(arr);
    }
}

在您的示例中,您试图返回外部调用者不知道的私有类的实例。在Arrays 示例中,返回的对象实际上是List(查看返回类型),而不是私有ArrayList

【讨论】:

  • 啊,我明白了;所以它返回的是“符合接口 List 的东西,但你不需要知道那是什么”,而不是对象本身,我现在明白了,谢谢
  • 出于兴趣,如果 ArrayList 提供了自己的额外方法,但 List 接口未定义(例如:extraMethod());我可以使用它吗?或者不是(我猜不是)?
  • @Motig 您将无法使用它,也不应该尝试(通过反射)。如果 ArrayList 类的创建者希望您能够使用该方法,他们会公开该类。
【解决方案2】:

Private 意味着标记为私有的类/字段/方法只能在当前范围内访问——即定义它的类。这意味着您从外部无法实例化新的 ArrayList,如数组类。但是,类中的成员可以使用类,就像 asList(T... a) 方法一样。

返回类型实际上是List&lt;T&gt;ArrayList&lt;T&gt; 的超类,因此您可以利用它,因为它是一个公共类,具有您的程序已知的方法。

该类被标记为静态,因为它不必是动态的;类的定义不会随着Arrays 的每个新实例而改变。

【讨论】:

  • 首先,List 是一个接口,而不是一个类,不是吗?所以我不能创建 List 的实例?因此它必须是一个 ArrayList?另外,我认为,在这种情况下,静态的含义在语言之间是不同的
  • @Motig 您不能创建 List&lt;T&gt; 的新实例,但可以创建实现 List 的类的新实例并将它们存储在 List 容器中 - 唯一可访问的方法将是 List 中定义的那些,因为它们必须被实现。见polymorphism
  • 我知道我可以使用任何符合 List 接口的对象作为 List,但不能使用 JVM 如何访问 ArrayList 中定义的实际实现,如果该实现被标记为私有;虽然我认为这是对程序员的私有访问和对运行时的私有访问之间的区别
【解决方案3】:

私有只是意味着它不能通过其接口在类之外访问。例如。你不能这样做:myObject.m_privateVariable。所发生的只是asList 'getter' 正在返回对私有变量的引用,因此通过受控方式公开它。

使用访问器(请参阅mutator methods)允许类控制对该数据的访问。例如,您可能会在返回私有变量之前对其进行一些操作,如果您让世界直接访问所有成员变量,您将无法在一次调用中完成。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-04
    • 1970-01-01
    • 2014-09-04
    • 2023-01-24
    相关资源
    最近更新 更多