我对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实例的第一个引用类型?我认为是引用类型,但不确定其在后台如何工作。!
我的问题听起来很愚蠢,但请帮助您理解这一点..!
谢谢
答案 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
时,它首先没有执行任何操作,因为先调用了参数,因此按有序顺序
new NOPLoggerRepository()
并创建一个新实例,该实例在堆上没有引用。new DefaultRepositorySelector
并确实要求它位于实例中的RepositorySelector
实例(没有任何引用)。简而言之。它仍然是出于参考,但只是在幕后。
答案 3 :(得分:-1)
您所指的通常称为dependency injection.,首先实例化要注入的对象,然后实例化从属对象。 SO answer here.