Подтвердить что ты не робот

Почему импорт класса не требуется при вызове метода в экземпляре (Java)

Что-то меня смутило - пример:

Thing.java:

import java.util.Date; 

class Thing { 
    static Date getDate() {return new Date();}
}

(тот же пакет) TestUsesThing.java:

// not importing Date here.

public class TestUsesThing {

    public static void main(String[] args) {
        System.out.println(Thing.getDate().getTime()); // okay
        // Date date = new Date(); // naturally this wouldn't be okay
    }

}

Почему нет необходимости импортировать Date, чтобы иметь возможность называть getTime() на одном из них?

4b9b3361

Ответ 1

Импорт в Java необходим только потому, что компилятор знает, что такое Date, если вы введете

Date date = new Date();

Импорт не похож на #include в C/С++; все типы на пути к классам доступны, но вы import просто не должны писать полное имя. И в этом случае это не нужно.

Ответ 2

Хороший вопрос!!

Я думаю, что результат заключается в различии между тем, как java-компилятор обрабатывает выражения против операторов.

Date d = new Date(); // a statement

где as

new Thing().getDate().getTime()

- это выражение, которое встречается внутри вызова метода println. Когда вы вызываете getDate в новом Thing(), компилятор пытается обработать выражение, просмотрев информацию типа для класса Thing, где он получает объявление типа Date. Но когда вы пытаетесь использовать Date отдельно в инструкции типа

Date d = new Thing().getDate();

вы назначаете результат типу в текущей области (класс TestUsesThing), компилятор пытается разрешить тип внутри этой области. В результате вы видите ошибку компилятора для неизвестного типа.

Ответ 3

Есть ли Thing и TestUsesThing в одном пакете? Если это так, вам не нужно импортировать Thing. Причина, по которой вам нужно импортировать Date, заключается в том, что она находится в другом пакете.

Ответ 4

Операторы

import используются для нескольких вещей.

  • Проверка типа компилятора и предотвращение столкновения имен.
  • Обеспечивает привязку байтового кода.

Всякий раз, когда мы говорим

System.out.println( new Thing().getDate().getTime() )

Компилятор анализирует это выражение слева направо и попадает в этот класс.

Разбор компилятора первого уровня.

  • Перейти к классу предметов
  • Компиляция не имеет никакой связи или ошибки ClassVersion от Thing.class

  • Check Thing.class имеет метод getDate.
  • Если # 3 хорошо, то указатель компилятора все еще находится в Thing.class(который имеет инструкции импорта даты), и я мог бы вызвать метод Time.
  • Как потребитель TestUsesThing получает только длинную переменную.

    System.out.println( new Thing().getDate() )
    

    5.1 В этом случае мы неявно обращаемся к методу .toString()

Ответ 5

На самом деле это был идеальный пример, так как существуют два разных стандартных класса Java Date: java.util.Date и java.sql.Date.

Как узнать, какой из них использовать? Просто. Метод getDate() объявляется как часть определения класса Thing, а частью этого объявления является его возвращаемый тип:

public java.util.Date getDate() {
  return this.date;
}

Конечно, если у вас есть импорт в определении класса Thing - и он не является двусмысленным, вы просто говорите:

public Date getDate() {

Если вы должны были декодировать двоичный файл класса Thing, вы увидите подпись метода метода getDate и включаете полное имя класса (включая пакет) возвращаемого типа.

import - это просто способ сообщить компилятору, какие пакеты вы хотите использовать при обращении к классам без явной квалификации. Список импорта будет проверяться всякий раз, когда будет видно неквалифицированное имя класса, и пакеты будут найдены. Если нет двусмысленности (например, импортирования java.util.date и java.sql.Date), этот класс будет использоваться. Если вы можете определить класс неявно или если имя класса полностью квалифицировано, вам не нужно импортировать.