Java import 문에 와일드카드를 사용하는 것이 왜 좋지 않습니까?

StackOverflow https://stackoverflow.com/questions/147454

  •  02-07-2019
  •  | 
  •  

문제

다음과 같은 단일 명령문을 사용하는 것이 훨씬 더 편리하고 깔끔합니다.

import java.awt.*;

여러 개의 개별 클래스를 가져오는 것보다

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

와일드카드를 사용하는 것이 잘못된 이유는 무엇입니까? import 성명?

도움이 되었습니까?

해결책

유일한 문제는 로컬 네임 스페이스를 막는 것입니다. 예를 들어, 스윙 앱을 쓰고 있다고 가정 해 봅시다. java.awt.Event, 또한 회사의 캘린더링 시스템과도 인터페이스하고 있습니다. com.mycompany.calendar.Event. 와일드 카드 방법을 사용하여 둘 다 가져 오면이 세 가지 중 하나가 발생합니다.

  1. 당신은 명백한 이름의 갈등이 있습니다 java.awt.Event 그리고 com.mycompany.calendar.Event, 따라서 컴파일조차 할 수 없습니다.
  2. 실제로 하나만 가져 오기 위해 관리합니다 (두 수입품 중 하나만 .*), 그러나 그것은 잘못된 것입니다. 그리고 당신은 코드가 왜 유형이 잘못되었다고 주장하는지 알아 내기 위해 고군분투합니다.
  3. 코드를 컴파일하면 아니오가 있습니다 com.mycompany.calendar.Event, 그러나 나중에 하나를 추가하면 이전에 유효한 코드가 갑자기 컴파일이 중지됩니다.

모든 가져 오기를 명시 적으로 나열하는 장점은 내가 당신이 사용하려는 클래스를 한눈에 알릴 수 있다는 것입니다. 빠른 일회성 일을하고 있다면 명시 적으로 아무것도 없습니다. 잘못된, 그러나 미래의 관리자는 그렇지 않으면 명확성에 감사드립니다.

다른 팁

여기 투표가 있습니다 ~을 위한 스타 수입.import 문은 다음을 가져오기 위한 것입니다. 패키지, 수업이 아닙니다.전체 패키지를 가져오는 것이 훨씬 더 깔끔합니다.여기서 확인된 문제(예: java.sql.Datejava.util.Date) 다른 방법으로 쉽게 해결할 수 있습니다. 정말 특정 수입품에 의해 다루어지며 확실히 모든 클래스에 대한 미친 현학적 수입품을 정당화하지는 않습니다.소스 파일을 열고 100개의 import 문을 읽어야 하는 것보다 더 당황스러운 것은 없습니다.

특정 가져오기를 수행하면 리팩토링이 더 어려워집니다.클래스를 제거하거나 이름을 바꾸면 제거해야 합니다. 모두 특정 수입품의.동일한 패키지의 다른 클래스로 구현을 전환하는 경우 가져오기를 수정해야 합니다.이러한 추가 단계는 자동화될 수 있지만 실제로는 실질적인 이득 없이 생산성에 타격을 줍니다.

Eclipse가 기본적으로 클래스 가져오기를 수행하지 않더라도 모든 사람은 여전히 ​​스타 가져오기를 수행할 것입니다.죄송합니다. 특정 수입품을 수행하는 데 대한 합리적인 정당성은 실제로 없습니다.

계급 갈등을 해결하는 방법은 다음과 같습니다.

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

내 기사를 참조하십시오 주문형 수입은 악합니다

요컨대, 가장 큰 문제는 수업이있을 때 코드가 중단 될 수 있다는 것입니다. 추가 당신이 가져 오는 패키지에. 예를 들어:

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

// ...

List list;

Java 1.1에서는 괜찮 았습니다. 목록은 java.awt에서 발견되었으며 갈등은 없었습니다.

이제 완벽하게 작동하는 코드를 확인하고 1 년 후 다른 사람이이를 편집하기 위해 가져오고 Java 1.2를 사용하고 있다고 가정합니다.

Java 1.2는 java.util에 목록이라는 인터페이스를 추가했습니다. 팔! 갈등. 완벽하게 작동하는 코드는 더 이상 작동하지 않습니다.

이것은 an입니다 사악한 언어 기능. 거기 있습니다 아니 유형이 유형이기 때문에 코드가 컴파일을 중지 해야하는 이유 추가 패키지에 ...

또한 독자가 사용중인 "FOO"를 결정하기가 어렵습니다.

이것의 ~ 아니다 Java 가져 오기 명세서와 함께 와일드 카드를 사용하는 것이 좋지 않습니다.

~ 안에 깨끗한 코드, Robert C. Martin은 실제로 장기 수입 목록을 피하기 위해 사용하는 것이 좋습니다.

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

J1 : 와일드 카드를 사용하여 긴 수입 목록을 피하십시오

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

가져 오기 패키지.*;

수입의 긴 목록은 독자에게 어려운 일입니다. 우리는 80 줄의 수입으로 모듈의 상단을 어지럽히고 싶지 않습니다. 오히려 우리는 수입이 우리가 어떤 패키지와 협력하는지에 대한 간결한 진술이되기를 원합니다.

특정 수입은 단단한 종속성이지만 와일드 카드 수입은 그렇지 않습니다. 클래스를 구체적으로 가져 오면 해당 클래스가 존재해야합니다. 그러나 와일드 카드가있는 패키지를 가져 오면 특정 클래스가 존재할 필요가 없습니다. 가져 오기 명령문은 이름을 사냥 할 때 패키지를 검색 경로에 추가합니다. 따라서 그러한 수입에 의해 진정한 의존성이 생성되지 않으므로 모듈을 덜 결합하게 유지하는 역할을합니다.

특정 수입의 긴 목록이 유용 할 수있는 경우가 있습니다. 예를 들어, 레거시 코드를 다루고 있고 모의와 스터브를 구축하는 데 필요한 클래스를 찾으려면 특정 수입 목록을 걸어 모든 클래스의 진정한 자격을 갖춘 이름을 찾은 다음 올릴 수 있습니다. 적절한 스터브가 제자리에 있습니다. 그러나 특정 수입에 대한 이러한 사용은 매우 드 rare니다. 또한 대부분의 최신 IDE를 사용하면 WildCarded 가져 오기를 단일 명령으로 특정 가져 오기 목록으로 변환 할 수 있습니다. 따라서 레거시의 경우에도 와일드 카드를 가져 오는 것이 좋습니다.

와일드 카드 수입은 때때로 이름 충돌과 모호성을 유발할 수 있습니다. 이름이 같지만 패키지가 다른 두 클래스는 특별히 가져 오거나 사용될 때 적어도 구체적으로 자격을 갖추어야합니다. 이것은 성가신 일 수 있지만 와일드 카드 수입을 사용하는 것이 일반적으로 특정 수입보다 더 낫기에 충분히 드 rare니다.

네임 스페이스를 방출하므로 모호한 클래스 이름을 완전히 지정해야합니다. 이것의 가장 흔한 일은 다음과 같습니다.

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

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

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

성능: 바이트 코드가 동일하기 때문에 성능에 영향을 미치지 않습니다. 비록 일부 컴파일 오버 헤드로 이어질 것입니다.

편집: 내 개인 기계에서는 아무것도 가져 오지 않고 빈 클래스를 컴파일하는 데 100ms가 걸리지 만 Java를 가져 오면 동일한 클래스가 필요합니다.* 170ms가 걸립니다.

  1. ClassName 충돌을 식별하는 데 도움이됩니다. 동일한 이름을 가진 다른 패키지의 두 클래스. 이것은 * 가져 오기로 마스킹 할 수 있습니다.
  2. 그것은 종속성을 명시 적으로 만들어서 나중에 코드를 읽어야하는 사람이라면 누구나 당신이 가져 오려는 것이 무엇인지, 그리고 당신이 가져 오려는 의미가 아닌 것을 알고 있습니다.
  3. 컴파일러가 전체 패키지를 검색하여 깊이를 식별 할 필요가 없기 때문에 일부 컴파일이 더 빨라질 수 있지만 일반적으로 현대적인 컴파일러와는 큰 일이 아닙니다.
  4. 명시 적 수입의 불편한 측면은 현대 IDE로 최소화됩니다. 대부분의 IDE를 사용하면 가져 오기 섹션을 붕괴시킬 수 있으므로 필요할 때 가져 오기를 자동으로 채우고 사용되지 않은 가져 오기를 자동으로 식별하여 청소를 돕습니다.

내가 일했던 대부분의 장소는 상당한 양의 Java를 사용하는 곳에서 명시 적 수입 수입을 코딩 표준의 일부로 만듭니다. 나는 때때로 빠른 프로토 타이핑을 위해 * 사용 *을 사용한 다음 코드를 생산할 때 가져 오기 목록 (일부 IDE가이를 수행 할 수 있음)을 확장합니다.

전체 파일을 보지 않고 파일에 사용 된 모든 외부 참조를 볼 수 있기 때문에 특정 가져 오기를 선호합니다. (예, 나는 그것이 완전히 자격을 갖춘 참조를 반드시 보여줄 필요는 없다는 것을 알고 있습니다. 그러나 가능할 때마다 피하십시오.)

이전 프로젝트에서 나는 *-임의에서 특정 수입으로 변경하면 컴파일 시간이 절반으로 줄어드는 것으로 나타났습니다 (약 10 분에서 약 5 분). *-임팩트는 컴파일러가 사용한 클래스와 일치하는 클래스에 나열된 각 패키지를 검색합니다. 이 시간은 작을 수 있지만 대규모 프로젝트에 추가됩니다.

*-임박의 부작용은 개발자가 필요한 것에 대해 생각하기보다는 일반적인 수입 라인을 복사하고 붙여 넣는 것이었다.

~ 안에 DDD 책

개발 기술이 무엇이든 구현이 기반을두고, 리팩토링 모듈의 작업을 최소화하는 방법을 찾으십시오. Java에서는 개별 클래스로 가져 오는 것을 피할 수는 없지만 패키지 이름 변경 노력을 동시에 줄이는 동시에 패키지가 응집력이 높은 단위라는 의도를 반영하여 한 번에 전체 패키지를 가져올 수 있습니다.

그리고 그것이 로컬 네임 스페이스를 막으면 당신의 잘못이 아닙니다 - 패키지의 크기를 비난하십시오.

가장 중요한 것은 그 가져 오기입니다 java.awt.* 미래의 Java 버전과 프로그램을 양립 할 수 없게 만들 수 있습니다.

"ABC"라는 클래스가 있다고 가정하고 JDK 8을 사용하고 있으며 가져 오기 java.util.*. 이제 Java 9가 나오고 패키지에 새로운 클래스가 있다고 가정합니다. java.util 우연의 일치는 "ABC"라고도합니다. 컴파일러는 "ABC"라는 이름으로 자신의 클래스 또는 새로운 클래스를 의미하는지 알지 못하기 때문에 이제 프로그램이 Java 9에서 컴파일하지 않습니다. java.awt.

해당 클래스 만 명시 적으로 가져 오면 그 문제가 없습니다. java.awt 당신이 실제로 사용하는 것.

자원:

Java 수입

양쪽에서 만들어진 모든 유효한 포인트 중에서 나는 와일드 카드를 피해야 할 주된 이유를 찾지 못했습니다. 코드를 읽고 모든 수업이 무엇인지 직접 알고 있거나 정의가 언어에 있지 않은지 또는 파일, 찾을 곳. 하나 이상의 패키지가 *로 가져 오면 * 내가 인식하지 못하는 클래스를 찾기 위해 그들 모두를 검색해야합니다. 가독성은 최고이며, 코드는하지 않아야한다는 데 동의합니다. 필요하다 그것을 읽는 IDE.

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

  • 씨# 언제나 할 수있는대로 * (암시 적으로) 사용합니다 using 패키지 이름. 클래스 이름을 전혀 지정할 수 없습니다. Java는 C#이후 기능을 소개합니다. (Java는 여러 측면에서 너무 까다 롭지만이 주제를 넘어선 다.

  • "수입 구성"을 할 때 Intellij 아이디어에서 동일한 패키지의 여러 가져 오기를 *로 자동으로 대체합니다. 이 기능은 꺼질 수 없으므로 맨 더 하나 기능입니다 (임계 값을 높일 수는 있지만).

  • 수락 된 답변에 나열된 사건은 유효하지 않습니다. * 없이는 여전히 같은 문제가 있습니다. 사용하든 아니든 코드에 Pakcage 이름을 지정해야합니다.

레코드의 경우 : 가져 오기를 추가하면 종속성을 나타냅니다.

파일의 종속성 (동일한 네임 스페이스의 클래스 제외)의 종속성이 무엇인지 빠르게 볼 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top