如何在对象运行时识别引用类型?

时间:2019-02-19 16:15:48

标签: java

我对Java引用类型的创建有疑问。

假设我下面有一节课

public class DefaultRepositorySelector
  implements RepositorySelector
{
  final LoggerRepository repository;

  public DefaultRepositorySelector(LoggerRepository repository)
  {
    this.repository = repository;
  }

  public LoggerRepository getLoggerRepository()
  {
    return this.repository;
  }
}

然后在另一个类的某个地方(如下面)调用类的构造函数DefaultRepositorySelector上的

repositorySelector = new DefaultRepositorySelector(new NOPLoggerRepository());

如您所见,我正在初始化类new DefaultRepositorySelector(new NOPLoggerRepository()),构造函数接受NOPLoggerRepository实例,该实例具有LoggerRepository接口的实现。

我的疑问是,我们直接将new NOPLoggerRepository()作为参数传递给构造函数,而该构造函数不是实例,不是引用类型,但是构造函数持有引用类型LoggerRepository

我无法理解这里的流程,因为在创建实例时根据流程,我们传递了新对象,但没有对该对象的引用,但是在类的定义构造函数中接受了该对象的引用类型。

因此,在运行时,当我们直接传递实例但方法或构造函数接受该实例的引用类型时,如何处理?谁创建了OR实例的第一个引用类型?我认为是引用类型,但不确定其在后台如何工作。!

我的问题听起来很愚蠢,但请帮助您理解这一点..!

谢谢

4 个答案:

答案 0 :(得分:1)

创建了一个类NOPLoggerRepository的对象并将其传递给该方法。 这是有效的,因为NOPLoggerRepository实现了LoggerRepository

关于何时不再可访问对象(并且可用于垃圾收集)的规则意味着在传递对象之前将不会对其进行收集(以防您担心这种怪异)。

构造函数完成后,DefaultRespositorySelector将保留对传入对象的引用。但是,在这种情况下,我们知道它的基础类是NOPLoggerRepository

一切都很好。编译器知道基础类型何时可能不是引用的显式类型,并通过各种机制确保正确的行为。 (对某些实现定义的全部内容进行光泽处理。)

在Java中,您永远不会“真正地”传递对象,而类变量不持有“对象”。 它们始终是对象的引用。

在随意的交谈中,我们通常会说诸如“我正在将NOPLoggerRespository传递给构造函数”之类的意思,但是我们的意思是我正在将对 NOPLoggerRespository的引用传递给构造函数。可以,因为只要我们都知道这是一个很好的速记,它就始终是参考。

答案 1 :(得分:0)

我不太确定我是否正确理解了你的问题。

您将使用名称DefaultRepositorySelector类型的repositorySelector创建对象。在调用构造函数时,您需要具有LoggerRepository的引用,该引用是对现有对象的引用(如果传递null,则为null)。

因此,要获取参考,请传递新的NOPLoggerRepository()。

首先评估括号中的表达式,因此在可以调用DefaultRepositorySelector的构造函数之前,将创建NOPLoggerRepository作为匿名对象。即,该对象已创建且未命名。但是我们有对其的引用,这意味着我们知道它在堆上的位置。

由于NOPLoggerRepository的类型为LoggerRepository,因此DefaultRepositorySelector的构造函数接受引用-将创建位于堆上的匿名对象的位置,并将创建名为repositorySelector的对象。

长话短说,在调用方法(或构造函数)之前,首先要评估参数(对象创建,数学计算,其他调用和评估的方法等),然后可以使用评估的参数来调用实际的方法。

答案 2 :(得分:0)

的基本概念
  

Java通过价值传递

对象中的

与谓词类型有很大不同。

在您的代码中:

repositorySelector = new DefaultRepositorySelector(new NOPLoggerRepository());

(new NOPLoggerRepository()被视为已被调用的代码作用域的忽略实例。 这里的事情是,当您调用new DefaultRepositorySelector时,它首先没有执行任何操作,因为先调用了参数,因此按有序顺序

    调用
  1. new NOPLoggerRepository()并创建一个新实例,该实例在堆上没有引用。
  2. 调用
  3. new DefaultRepositorySelector并确实要求它位于实例中的RepositorySelector实例(没有任何引用)。
  4. JVM在构造函数中为该对象创建唯一的引用,然后在类a中创建另一个引用(当构造函数弹出时)。

简而言之。它仍然是出于参考,但只是在幕后。

答案 3 :(得分:-1)

您所指的通常称为dependency injection.,首先实例化要注入的对象,然后实例化从属对象。 SO answer here.