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

Почему я получаю это предупреждение о классах утилиты в Java

Я изучаю Java и OOPS, а при программировании базового Hello World в eclipse я вижу желтый треугольник, говорящий, что классы 'не должны иметь публичный или стандартный конструктор. Я не могу понять, почему именно это происходит и что это значит? Что я делаю неправильно?

class HelloWorld {


public static void main(String[] args)
{
    // TODO Auto-generated method stub
            System.out.println("Hola Mundo!");

}


  }

EDIT1: отредактирован код для включения предлагаемых изменений.

final class HelloWorld {


private HelloWorld()
{
    throw new AssertionError("Instantiating utility class...");

}
public static void main(String[] args)
{
    // TODO Auto-generated method stub
            System.out.println("Hola Mundo!");

}


}

По-прежнему получать предупреждение в строке класса HelloWorld.

Edit2:

Создал новый класс, и теперь он работает. Спасибо, Джон. Почему старый класс все еще предупреждает? Богемский, я до сих пор не знаю о концепциях, упомянутых вами в вашем посте. Я вернусь к ним, когда пойду лучше. Спасибо, что объяснили.

4b9b3361

Ответ 1

Это означает, что кто-то может написать:

HelloWorld helloWorld = new HelloWorld();

когда вы, вероятно, не хотите их - вы не предоставляете никаких членов экземпляра, поэтому зачем им создавать экземпляры? Перепишите свой код как:

final class HelloWorld {

    private HelloWorld() {
        // Prevent instantiation
        // Optional: throw an exception e.g. AssertionError
        // if this ever *is* called
    }

    public static void main(String[] args) {
        System.out.println("Hola Mundo!");
    }
}

Ответ 2

Что сказал Джон, но вы также должны знать, что каждый класс имеет конструктор, объявляете ли вы один или нет. Если вы не объявляете одно, то для вас неявно определяется "конструктор по умолчанию".

Другими словами, эти два класса идентичны поведению:

public class ClassA {
}


public class ClassB {
    public ClassB() {
    }
}

BEWARE: наличие частного конструктора не предотвращает создание экземпляра!

И только чтобы быть анальным, наличие частного конструктора не позволяет помешать кому-либо создавать экземпляр вашего класса, это просто усложняет:

Есть (по крайней мере) два способа обойти это:

Объявить метод factory (очевидно, но если это код вашей компании, кто-то может это сделать):

public class ClassA {
    private ClassA() {}

    public static ClassA create() {
        return new ClassA(); // oops! this one got away
    }
}


Используйте рефлексию (подлый, и как-то кажется неправильным, но это работает!):

public class ClassA {
    private ClassA() {}
}

// Elsewhere, in another class across town:
Constructor<?> constructor = ClassA.class.getDeclaredConstructor();
// constructor private? no problem... just make it not private!
constructor.setAccessible(true); // muhahahaha
Object obj = constructor.newInstance();
System.out.println(obj.getClass().getSimpleName());  // Prints ClassA!

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

Ответ 3

Для полноты ни один из респондентов до сих пор не прокомментировал другую проблему с вашим первоначальным классом

class HelloWorld {

который, как было предложено, вы превратились в

final class HelloWorld {

Ключевое слово final на классе Java запрещает другим классам распространять (наследовать) его. Если вы не делаете финальный класс, расширяемый класс может использовать всевозможные вещи, которые вы, возможно, не планировали, поскольку расширяемый класс имеет доступ к членам protected унаследованного класса.

Хорошая практика всегда делать ваши классы как abstract или final, а значит, они предназначены для только, или не для наследования. Будет много раз, когда вы создадите класс как реальный (не абстрактный), так и расширяемый (не окончательный), но принятие этого осознанного решения - хорошая привычка вступать.

Ответ 4

Самый простой способ написать класс утилиты - это перечисление без экземпляров. Вы можете работать с Java 5.0 и выше.

public enum Utility {;
    public static void main(String... args) {
        System.out.println("Hola Mundo!");
    }
}

Вам не нужно определять частный конструктор, и вы не можете создавать экземпляры с использованием внутренних классов или других трюков, таких как отражение. (Если вы игнорируете класс Unsafe;)

BTW: некоторые видят использование enum как взлома, но для меня он явно говорит "У меня есть класс без экземпляров", а не для предотвращения создания экземпляров, которые являются косвенными.