source

Java Import 스테이트먼트에 와일드 카드를 사용하는 것이 나쁜 이유는 무엇입니까?

factcode 2022. 8. 16. 23:15
반응형

Java Import 스테이트먼트에 와일드 카드를 사용하는 것이 나쁜 이유는 무엇입니까?

다음과 같은 단일 문장을 사용하는 것이 훨씬 편리하고 깨끗합니다.

import java.awt.*;

여러 개의 개별 클래스를 수입하는 것보다

import java.awt.Panel;
import java.awt.Graphics;
import java.awt.Canvas;
...

에서 와일드카드를 사용하면 어떤 문제가 있습니까?import스테이트먼트?

유일한 문제는 로컬 네임스페이스를 어지럽힌다는 것입니다.예를 들어, Swing 앱을 만들고 있다고 가정해 봅시다.그래서 필요한 것은java.awt.Event, 또한 회사의 캘린더 시스템과 상호 작용하고 있습니다.com.mycompany.calendar.Event와일드카드 방식을 사용하여 둘 다 Import할 경우 다음 3가지 중 하나가 수행됩니다.

  1. 상호간에 명백한 이름 경합이 있습니다.java.awt.Event그리고.com.mycompany.calendar.Event컴파일도 할 수 없습니다.
  2. 실제로는 1개만 Import 할 수 있습니다(2개의 Import 중1개만 Import 할 수 있습니다)..*잘못된 코드입니다.또한 코드가 잘못된 코드라고 주장하는 이유를 파악하는데 어려움을 겪고 있습니다.
  3. 코드를 컴파일 할 때,com.mycompany.calendar.Event그러나 나중에 추가될 때 이전에 유효한 코드가 갑자기 컴파일을 중지합니다.

모든 Import를 명시적으로 나열하는 것의 장점은 당신이 사용하려는 클래스를 한눈에 알 수 있기 때문에 코드를 쉽게 읽을 수 있다는 것입니다.단발적인 작업이라면 특별히 문제될 것은 없지만, 그렇지 않으면 미래의 유지관리 담당자는 명확한 설명에 감사할 것입니다.

스타 수입에 대한 투표입니다.가져오기 문은 클래스가 아니라 패키지를 가져오기 위한 것입니다.패키지 전체를 Import 하는 것이 훨씬 깨끗합니다.여기서 특정된 문제(예:java.sql.Datejava.util.Date)는 다른 방법으로 쉽게 해결되며, 특정 수입품에 의해 실제로 다루어지지 않으며, 모든 계층에 대해 터무니없이 현학적인 수입을 정당화하지 않는다.소스 파일을 열어 100개의 Import 스테이트먼트를 페이지화해야 하는 것보다 더 혼란스러운 것은 없습니다.

특정 Import를 실행하면 리팩터링이 더욱 어려워집니다.클래스를 삭제/변경할 경우 해당 클래스의 모든 특정 Import를 제거해야 합니다.구현을 동일한 패키지의 다른 클래스로 전환하면 가져오기를 수정해야 합니다.이러한 추가 단계는 자동화할 수 있지만, 실제로는 아무런 이익도 얻을 수 없는 생산성 저하입니다.

Eclipse가 기본적으로 특정 클래스 가져오기를 수행하지 않았다면 모든 사용자가 여전히 스타 가져오기를 수행했을 것입니다.죄송하지만, 특정 수입을 할 수 있는 합리적인 근거가 없습니다.

계층 간 충돌에 대처하는 방법은 다음과 같습니다.

import java.sql.*;
import java.util.*;
import java.sql.Date;

내 기사 "Import on Demand is Evil"을 참조하십시오.

즉, 가장 큰 문제는 Import한 패키지에 클래스가 추가되면 코드가 깨질 수 있다는 것입니다.예를 들어 다음과 같습니다.

import java.awt.*;
import java.util.*;

// ...

List list;

Java 1.1에서는 문제가 없었습니다.리스트는 java.awt에서 발견되어 경합은 발생하지 않았습니다.

이제 완벽하게 동작하는 코드를 체크인하고 1년 후 다른 사용자가 코드를 가져와 편집하고 Java 1.2를 사용하고 있다고 가정해 보겠습니다.

Java 1.2는 java.util에 List라는 이름의 인터페이스를 추가했습니다.쿵! 충돌.완벽하게 작동하던 코드가 더 이상 작동하지 않습니다.

이것은 EVAL 언어 기능입니다.패키지에 유형이 추가되었다고 해서 코드 컴파일을 중지할 이유는 없습니다.

게다가 독자는, 어느 「Foo」를 사용하고 있는지를 판단하기 어렵습니다.

Java Import 스테이트먼트에 와일드 카드를 사용하는 것도 나쁘지 않습니다.

클린 코드, 로버트 C.마틴은 실제로 긴 수입 목록을 피하기 위해 그것들을 사용하는 것을 권장합니다.

권장사항은 다음과 같습니다.

J1: 와일드카드를 사용한 긴 Import 목록 회피

패키지에서 두 개 이상의 클래스를 사용하는 경우 패키지 전체를 Import합니다.

패키지를 Import합니다.*;

긴 수입품 목록은 독자들에게는 벅차다.80라인의 수입품으로 모듈 상부를 어지럽히고 싶지 않습니다.Import는 어떤 패키지와 협업하는지에 대한 간결한 문구가 되길 바랍니다.

특정 Import는 하드 종속성이지만 와일드카드 Import는 그렇지 않습니다.특정 클래스를 Import하는 경우 해당 클래스가 존재해야 합니다.그러나 와일드카드를 사용하여 패키지를 Import할 경우 특정 클래스가 존재할 필요가 없습니다.Import문은 이름 헌팅 시 검색 경로에 패키지를 추가합니다.따라서 이러한 Import를 통해 진정한 의존관계가 형성되지 않으며, 따라서 이러한 의존관계는 모듈의 결합성을 떨어뜨리는 역할을 합니다.

특정 수입품의 긴 목록이 유용할 수 있습니다.예를 들어, 레거시 코드를 취급하고 있으며, 어떤 클래스용으로 mock 및 stub을 빌드해야 하는지 알아보려면 특정 Import 목록을 아래로 이동하여 모든 클래스의 진정한 수식 이름을 찾은 후 적절한 stub를 배치합니다.그러나, 특정의 수입에 이러한 용도는 매우 드물다.또한 대부분의 최신 IDE에서는 와일드카드 Import를 하나의 명령으로 특정 Import 목록으로 변환할 수 있습니다.따라서 레거시 경우에도 와일드카드를 Import하는 것이 좋습니다.

와일드카드 Import로 인해 이름 경합이나 애매모호함이 발생할 수 있습니다.이름이 같지만 패키지가 다른 두 개의 클래스를 구체적으로 가져오거나 사용할 경우 최소한 구체적으로 수식해야 합니다.이는 번거로운 일이 될 수 있지만 와일드카드 Import를 사용하는 것이 특정 Import보다 일반적으로 더 나을 정도로 드문 경우입니다.

퍼포먼스:바이트 코드가 같기 때문에 퍼포먼스에 영향은 없습니다.컴파일 오버헤드가 발생합니다.

컴파일: 개인 머신에서는 아무것도 Import하지 않고 빈 클래스를 컴파일할 때 java를 Import할 때 100밀리초 걸리지만 동일한 클래스가 소요됩니다.* 170밀리초 걸립니다.

네임스페이스가 복잡해지기 때문에 애매한 클래스 이름을 완전히 지정해야 합니다.가장 일반적인 원인은 다음과 같습니다.

import java.util.*;
import java.awt.*;

...
List blah; // Ambiguous, needs to be qualified.

또한 모든 종속성이 파일 맨 위에 나열되므로 종속성을 구체화하는 데 도움이 됩니다.

  1. 클래스 이름 충돌을 식별하는 데 도움이 됩니다. 즉, 이름이 같은 서로 다른 패키지에 있는 두 개의 클래스입니다.이것은 * Import로 마스킹할 수 있습니다.
  2. 따라서 나중에 코드를 읽어야 하는 모든 사용자가 Import하려는 내용과 Import 의도하지 않은 내용을 알 수 있습니다.
  3. 컴파일러가 디폴트를 식별하기 위해 패키지 전체를 검색할 필요가 없기 때문에 컴파일러를 고속화할 수 있습니다.다만, 이것은 현대의 컴파일러에서는 큰 문제가 되지 않습니다.
  4. 현대 IDE를 통해 명시적 수입의 불편한 측면을 최소화합니다.대부분의 IDE에서는 Import 섹션을 축소하여 방해가 되지 않도록 하고 필요할 때 Import를 자동으로 채우고 사용하지 않는 Import를 자동으로 식별하여 정리할 수 있습니다.

제가 일해 본 대부분의 Java는 명시적인 Import를 코딩 표준의 일부로 만듭니다.지금도 *를 사용하여 빠른 프로토타이핑을 한 후 Import 목록을 확장합니다(일부 IDE도 이 기능을 제공합니다).

파일 전체를 볼 필요 없이 파일에 사용된 외부 참조를 모두 볼 수 있기 때문에 특정 가져오기를 선호합니다(예, 완전한 참조를 표시할 필요는 없습니다).하지만 가능한 한 피하고 있습니다.)

이전 프로젝트에서는 *-imports에서 특정 Import로 변경함으로써 컴파일 시간이 절반으로 단축되었습니다(약 10분에서 약 5분으로).*-import를 사용하면 컴파일러는 목록에 있는 각 패키지에서 사용자가 사용한 클래스와 일치하는 클래스를 검색합니다.이 시간은 짧을 수 있지만 대규모 프로젝트에는 도움이 됩니다.

*-import의 부작용은 개발자들이 그들이 필요로 하는 것을 생각하지 않고 공통의 수입 라인을 복사하여 붙여넣는다는 것입니다.

DDD북에서

구현의 기반이 되는 개발 테크놀로지가 무엇이든 모듈 리팩터링 작업을 최소화하는 방법을 찾아보세요.Java에서는 개별 클래스로 Import하는 것은 피할 수 없지만 패키지가 높은 응집력인 동시에 패키지 전체를 Import할 수 있습니다.g 패키지 이름을 변경하기 위한 노력.

로컬 네임스페이스를 어지럽히는 경우는, 패키지의 사이즈를 탓해 주세요.

  • 컴파일러는 자동으로 *를 구체적인 클래스 이름으로 대체하므로 런타임에 미치는 영향은 없습니다..class 파일을 디컴파일하면import ...*.

  • C#은 항상 *(암시적으로)를 사용합니다.using패키지 이름클래스 이름은 전혀 지정할 수 없습니다.Java는 c# 뒤에 이 기능을 도입했습니다.(Java는 여러 면에서 매우 까다롭지만 이 주제를 벗어납니다.)

  • Intelij Idea에서는 Import를 정리하면 동일한 패키지의 여러 Import가 자동으로 *로 대체됩니다.이 기능은 임계값을 늘릴 수 있지만 끌 수 없기 때문에 필수 기능입니다.

  • 접수된 답변에 기재된 케이스는 유효하지 않습니다.*가 없어도 같은 문제가 발생합니다.* 를 사용하든 사용하지 않든 코드에 pakcage 이름을 지정해야 합니다.

가장 중요한 것은 수입하는 것입니다.java.awt.*사용 중인 프로그램이 향후 Java 버전과 호환되지 않을 수 있습니다.

"ABC"라는 이름의 클래스가 있고 JDK 8을 사용하여java.util.*이제 Java 9가 출시되어 패키지에 새로운 클래스가 포함된다고 가정해 보겠습니다.java.util우연히도 "ABC"라고 불리게 된다.컴파일러는 "ABC"라는 이름이 자신의 클래스를 의미하는지 아니면 새로운 클래스를 의미하는지 알 수 없기 때문에 프로그램이 Java 9에서 컴파일되지 않습니다.java.awt.

이러한 클래스만 명시적으로 Import하면 문제가 발생하지 않습니다.java.awt사용할 수 있습니다.

자원:

Java Imports

다음은 이 주제에 대해 제가 발견한 몇 가지 사항입니다.

  • 컴파일 중에 컴파일러는 .* Import에서 코드로 사용되는 클래스를 검색하려고 합니다.그러면 .* Import에서 사용된 클래스를 선택하여 대응하는 바이트 코드가 생성됩니다.따라서 .* Import 또는 .class names Import를 사용하는 바이트코드는 동일하며 같은 바이트코드로 인해 런타임 퍼포먼스도 동일합니다.

  • 컴파일러는 각 컴파일에서 .* 패키지의 모든 클래스를 스캔하여 코드에서 실제로 사용되는 클래스와 일치시켜야 합니다.따라서 .* Import를 사용하는 코드는 .class name Import를 사용하는 경우와 비교하여 컴파일 프로세스 중에 시간이 걸립니다.

  • .* Import를 사용하면 코드를 보다 깔끔하게 만들 수 있습니다.

  • .* Import를 사용하면 두 개의 다른 패키지에서 같은 이름의 두 개의 클래스를 사용할 때 모호성이 발생할 수 있습니다.예를 들어, 날짜는 두 패키지로 제공됩니다.

      import java.util.*;
      import java.sql.*;
    
      public class DateDemo {
          private Date utilDate;
          private Date sqlDate;
      }
    

양측의 모든 유효한 점들 중에서 나는 와일드카드를 피해야 할 주된 이유를 찾지 못했다.코드를 읽고 모든 클래스가 무엇인지, 언어나 파일에 정의되어 있지 않은 경우, 어디에 있는지 직접 알 수 있는 것이 좋습니다.패키지가 여러 개 Import된 경우 *를 사용하여 모든 패키지를 검색하여 인식할 수 없는 클래스를 찾아야 합니다.가독성은 최고이며 코드를 읽기 위해 IDE가 필요하지 않다는 것에 동의합니다.

기록의 경우:가져오기를 추가하면 종속성도 표시됩니다.

파일의 종속성을 빠르게 확인할 수 있습니다(같은 네임스페이스의 클래스는 제외).

어수선한 네임스페이스는 잊어버리고...그리고 GitHub, vi, Notepad+, 또는 IDE 이외의 텍스트 에디터에서 당신의 코드를 읽고 이해해야 하는 불쌍한 영혼에 대해 생각해 보세요.

그 사람은 와일드카드 스코프의 모든 클래스와 참조에 대해 와일드카드 중 하나에서 나오는 모든 토큰을 열심히 찾아봐야 합니다.도대체 무슨 일이 일어나고 있는지 알기 위해서요

컴파일러 전용으로 코드를 쓰는 경우, 그리고 자신이 무엇을 하고 있는지 알고 있다면, 와일드 카드에는 문제가 없을 것입니다.

그러나 미래의 당신을 포함한 다른 사람들이 특정 코드 파일을 한 번 읽어보고 빠르게 이해하기를 원한다면 명시적인 참조가 많은 도움이 됩니다.

패키지의 모든 클래스를 Import하는 것은 블라인드 접근법으로 간주됩니다.그 주된 이유는 클래스 네임스페이스를 혼란스럽게 하고 같은 이름의 다른 패키지의 클래스 간에 경합을 일으킬 수 있기 때문입니다.

필요한 클래스를 구체적으로 입력하면 이러한 문제가 발생하지 않고 원하는 버전이 명확하게 표시됩니다.이것은 코드 유지보수에 도움이 됩니다.

Oracle의 Java 튜토리얼에서는 와일드카드 Import를 사용하기 때문에 와일드카드 Import를 사용하는 것도 나쁘지 않습니다.오라클의 자바 사람들이 나쁜 짓을 할 거라고 생각하지 않아요.

여기를 봐주세요.https://docs.oracle.com/javase/tutorial/uiswing/examples/components/CustomComboBoxDemoProject/src/components/CustomComboBoxDemo.java

위 프로그램에서는 와일드카드 Import를 사용합니다.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

https://docs.oracle.com/javase/tutorial/uiswing/examples/components/ 에서 더 많은 프로그램을 보실 수 있습니다.

언급URL : https://stackoverflow.com/questions/147454/why-is-using-a-wild-card-with-a-java-import-statement-bad

반응형