새 객체를 저장하지 않고 생성하는 것은 나쁜 습관입니까?


23

객체에 대한 참조를 저장하지 않고 Java 코드로 작성된 객체를 보았습니다. 예를 들어, 이클립스 플러그인에서 다음과 같이 생성 된 SWT 셸을 보았습니다.

new Shell();

이 새로운 Shell 객체는 변수에 저장되지 않지만, 윈도우가 닫힐 때 기본적으로 발생하는 윈도우가 배치 될 때까지 참조 된 상태로 유지됩니다.

이것에 대한 참조를 저장하지 않고 이와 같은 객체를 생성하는 것은 나쁜 습관입니까? 아니면 도서관이 제대로 설계되지 않았습니까? 참조가 필요하지 않고 개체의 "부작용"만 원하는 경우 어떻게합니까? 어쨌든 참조를 저장해야합니까?

최신 정보:

분명히, 위의 예는 좋지 않습니다. 이와 같이 생성 된 UI 요소를 보았지만 이와 같은 SWT 셸을 만드는 것은 셸 인스턴스에서 open 메서드를 호출해야하기 때문에 의미가 없습니다. 있다 AIX에서 제공하는 좋은 예 하여에서 다음과 같은 자바 동시성 튜토리얼 :

(new HelloThread()).start();

이 관행은 많은 상황에서 볼 수 있으므로 질문이 남아 있습니다. 좋은 습관입니까?


2
참조를 저장하는 요점은 무엇입니까?
Daniel R은

(아마도 개념적 관점 Shell.createTopLevelShell()에서이 경우 생성자를 사용하는 것과 같은 정적 방법을 사용하는 것이 좋습니다. 그러나 기능상 차이는 거의 없습니다.)
Daniel R Hicks

이 질문은 객체를 참조하지 않고 객체를 작성하는 방법,이 방법이 필요한 클래스를 작성하는 것, 또는 SWT가 이러한 종류의 패턴을 사용하는 방법에 관한 것입니까?
StriplingWarrior

1
SWT 객체는 dispose()d 여야합니다 . 규칙 1 : 객체 를 만든 경우 폐기합니다. eclipse.org/articles/swt-design-2/swt-design-2.html
jbindel

2
디버깅 목적으로 변수를 사용하여 참조를 보유합니다. 이 방법에 중단 점이 있으면 디버거가 로컬 변수를 통해 객체를 쿼리하도록 할 수 있습니다. 참조가 없으면 가능하지만 훨씬 어려울 것입니다.
Martin York

답변:


12

개인적으로 선호하는 요소가 있지만 참조를 저장하지 않는 것이 반드시 나쁜 습관은 아니라고 생각합니다.

다음과 같은 가상의 예를 고려하십시오.

new SingleFileProcessor().process(file);

모든 파일에 대해 새 프로세서 개체를 만들어야하고 process()호출 후에 필요하지 않은 경우 해당 파일에 대한 참조를 저장할 필요가 없습니다 .

다음은 Java 동시성 학습서 에서 가져온 또 다른 예입니다 .

(new HelloThread()).start();

참조가 저장되지 않은 다른 많은 예제를 보았으며 다음과 같이 내 눈에 완벽하게 읽 힙니다.

String str = new StringBuilder().append(x).append(y).append(z).toString();

( StringBuilder객체는 유지되지 않습니다.)

common.lang 's HashCodeBuilderet al. 과 비슷한 패턴이 있습니다 .


2
@ BalusC : 관련하여, 비린내가 무엇이고 어떤 방법으로 공장 방법이 더 나은지 getInstance()알지 못합니다 (귀하의 예가 내 것과 유사 하고 단일 공장이 아니라 공장 이라고 가정합니다 ).
NPE

싱글 톤 사용 여부는 공장에서 결정합니다. 공장의 발신자는 그것에 대해 너무 많이 생각해서는 안됩니다.
Donal Fellows

예제에서 FileProcessor 인스턴스는 명령문이 완료되면 필요하지 않지만 OP의 예제에서 쉘 인스턴스는 다른 오브젝트에서 참조하고 (커버 아래에서) 참조 (및 따라서 Shell 오브젝트)는 진술 기간.
Daniel R은

@BalusC : FileProcessor에는의 동작을 변경하는 추가 메소드가있을 수 있습니다 process.
케빈 클라인

7

생성 된 객체에 대한 참조가 필요 하지 않으면 참조를 유지하지 마십시오. 그렇게 간단합니다.


5

일반적으로 참조를 릴리스 할 수있는 한 빨리 릴리스하는 것이 좋습니다. 나는 다음과 같은 차이점이 없다.

HelloThread thread = new HelloThread();
thread.start();
// where thread is never used for the rest of the method

(new HelloThread()).start();

코드와 관련하여 변수 이름을 사용하지 않는 것이 좋습니다. 이는 긍정적 일 수 있습니다. JIT 컴파일러는 일반적으로 마지막 사용 후 스레드를 가비지 수집 할 수 있다는 점을 인식 할만큼 충분히 영리하므로 성능 관점과 차이가 없을 것입니다.

피해야 할 유일한 문제 는 Constructor Anti-Pattern코드 이지만, 그것이 당신이 요구하는 것 같지는 않습니다.


3

SWT를 사용하는 경우에는 나빠질 수 있습니다 (dispose () 메소드 호출). 그러나 다른 클래스 (SWT가 아닌)의 경우 괜찮습니다.

운영 체제 리소스 관리에 대한 기사입니다.


순환 참조는 객체가 Java에서 가비지 수집되는 것을 막지 않습니다. 최신 Java VM은 객체가 도달 가능한지 여부에 따라 객체가 GCable인지 확인하고 참조 횟수를 사용하지 않습니다.
jbindel

2
실제로 참조 카운팅을 사용하지 않습니다. 그러나 SWT는 dispose ()를 호출해야하는 특별한 경우이지만, retain ()을 먼저 호출 할 필요는 없습니다.
Alex

나는 비 SWT 사건만을 언급하려고했다.
jbindel

다음은 운영 체제 자원 관리에 대한 기사입니다. eclipse.org/articles/swt-design-2/swt-design-2.html
Alex

2
이 경우 오해의 소지가 있으므로“GC에 불가능”에 대한 설명을 제거하도록 답변을 편집하십시오.
Donal Fellows

1

우선, Java보다 C 또는 C ++를 배운 사람들을 귀찮게 할 것입니다. 독자가 그것이 찬사인지 죄인인지를 결정하는 연습으로 남겨 두겠습니다.

객체가 매우 오래 지속 되도록 설계된 상황이 있지만, 대부분 무언가가 객체를 만들기에 충분히 복잡한 경우에는 참조를 유지해야 할 충분한 이유가 있으므로 복잡하게 유지해야합니다. 최소한 무언가를 놓친 경우 다시 확인하라는 경고가 표시됩니다.

예를 들어, 튜토리얼에서 스레드 참조를 유지하는 데 관심이없는 사람은 없지만 실생활에서 스레드를 생성하는 데 시간이 오래 걸리면 스레드를 취소 할 수있을 정도로 시간이 오래 걸립니다. 또는 수명이 짧으면 일반적으로 join계속 하기 전에 원하는 스레드를 생성합니다 . 또는 스레드 생성이 실제로 성공했는지 확인하려고합니다. 또는 종료하기 전에 실이 깨끗하게 마무리되도록하려고합니다. 당신은 그림을 얻는다.


2
다른 언어의 성가신 프로그래머에 대한 걱정이 실제로 첫 번째 관심사입니까?
Buttons840

팀 구성에 따라 가독성 / 친숙성 / 스타일 문제가됩니다. 많은 사람들이이 스타일을 사용하기 때문입니다. C ++로 프로그래밍 한 적이없는 사람들조차도 종종 멘토의 스타일을 채택합니다.
Karl Bielefeldt
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.