Чому Java не використовує інкапсуляцію з деякими класами?


25

Моє запитання пов'язане з класами System.inта System.outкласами (можуть бути такі, як у бібліотеці Standard). Чому так? Це не погана практика в ООП? Чи не слід його використовувати так: System.getIn()і System.getOut()? У мене завжди було це запитання, і я сподіваюся, що тут знайду хорошу відповідь.

Відповіді:


36

Визначення для inта outполів у Systemкласі:

public final static PrintStream out;
public final static InputStream in;

Це константи. Вони бувають і об'єктами, але вони є константами. Це дуже те саме, що і клас Math:

public static final double E = 2.7182818284590452354;
public static final double PI = 3.14159265358979323846;

Або в булевому класі:

public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);

Або в класі кольорів:

public final static Color white     = new Color(255, 255, 255);
public final static Color black     = new Color(0, 0, 0);
public final static Color red       = new Color(255, 0, 0);

При зверненні до публічної константи, яка не змінюється, немає значної переваги для її інкапсуляції - концептуально чи на основі продуктивності. Її там. Це не зміниться.

Немає реальної різниці між Color.whiteта System.out.


Ну, я цього не бачив, це постійні об'єкти. Це досить хороше пояснення.
Clawdidr

1
@Clawdidr на сьогоднішній Java, можна подумати про використання їх enumдля утримання ... хоча це enumбуло новим у Java 1.5 (не варіант за 1.0 дня).

Лише з цікавості (не сам розробник Java): чи є різниця між final staticі static final? Якщо так, що це?
Мар'ян Венема

1
@MarjanVenema немає різниці, просто віддали перевагу порядку модифікаторів. чек модифікатора контрольного стилю показує бажаний порядок. Мабуть, хто б не написав ці два вихідні файли у jdk-версії, я не погодився на замовлення. Це просто умовність.

:) і дякую Майклу, що знайшли час для відповіді та за посилання.
Мар'ян Венема

5

Справжня причина полягає в тому, що це спадщина. Ці System.in,out,errконстанти були частиною Java 1.0 ... і , ймовірно, набагато далі. На той час, коли було зрозуміло, що в дизайні виникли проблеми, виправити це було вже пізно. Найкраще, що вони могли зробити, було додати System.setIn,setOut,setErrметоди в Java 1.1, а потім розібратися з питаннями мовної специфікації 1 .

Це схоже на питання, чому існує статичний System.arraycopyметод, ім'я якого порушує умови імен Java.


Що стосується того, це "поганий дизайн" чи ні, я думаю, що це так. Бувають ситуації, коли поточне поводження, що не пов’язане з ООС, є серйозною проблемою. (Подумайте ... як можна запустити одну програму Java всередині іншої, коли їх "стандартний IO" потік вимог суперечить. Подумайте ... код тестування блоку, який тягне за собою зміну потоків.)

Однак я можу також звернутися до аргументу про те, що сучасний спосіб виконання справ є більш зручним у багатьох випадках.


1 - Цікаво зазначити, що System.in,out,errзмінні в JLS мають особливу згадку як такі, що мають "особливу семантику". JLS говорить, що якщо ви зміните значення finalполя, поведінка не буде визначеною ... за винятком цих полів.


2

Я вважаю, що зовнішній об'єкт є незмінним, що робить його якось безпечним (це дискусійно) для зберігання в загальнодоступному статичному полі.

Багато класів в JDK не дотримуються кращих об'єктно-орієнтованих принципів дизайну. Однією з причин цього є той факт, що вони були написані майже 20 років тому, коли Орієнтація на об'єкти лише формувалася як парадигма мейнстріму, і багато програмістів просто не були знайомі з ними, як зараз. Дуже хорошим прикладом поганого дизайну API є API Date & Time, який знадобився їм 19 років, щоб змінити ...


3
Я б зробив твердження ще сильнішим, публічна остаточна змінна (статична чи ні) точно така ж "безпечна", як і геттер, і я вважаю за незмінність над парою сетер / геттер. У сеттерів майже завжди погана ідея (Незмінне це добре - і якщо це не може бути незмінним метод, який "встановлює", він, мабуть, заслуговує і трохи ділової логіки), Якщо вам потрібен геттер, ви можете також оприлюднити його остаточне, але робити жодне не бажано - не запитуйте клас про його дані, попросіть клас зробити щось з його даними.
Білл К

@BillK: Так, також відомий як Закон Деметера (хоча це не закон, а швидше керівництво).
sleske

2

Ця відповідь чудова і правдива.

Я хотів би додати, що в деяких випадках йдуть компроміси заради зручності використання.

Об'єкти типу String можна створити інстанціювати без нової події, коли String не є примітивом:

String s = "Hello";

Рядок, що є непомітивним, має бути створений таким чином:

String s = new String("Hello");          // this also works 

Але компілятор допускає більш короткі, менші опції OO, оскільки String - це на сьогоднішній день найбільш широко використовуваний клас в API.

Також масиви можуть бути ініціалізовані неоновим способом:

int i[] = {1,2,3};

Як не дивно, об'єкт є або екземпляром класу, або масивом . Значення масивів - це абсолютно окремий тип класу.

Масиви мають lengthпублічне поле, яке не є постійною. Також жодна документація на масиви класів не є примірником. (не плутати з класом Arrays або java.reflect.Array).

int a = myArray.length;    // not length()

6
Тебе різні речі - new String("Hello")завжди створюватимуть новий об'єкт String. Поки String s = "Hello";буде використовувати інтернований об’єкт. Порівняйте: "Hello" == "Hello"може бути правдою, тоді new String("Hello") == new String("Hello")як завжди неправдою. Існує магія оптимізації часу компіляції, що відбувається в перше, що неможливо new String("Hello"). Дивіться en.wikipedia.org/wiki/String_interning

@MichaelT Я додав додаткову безтурботність на масивах, просто заради повноти.
Тулен Кордова

2
@Tarik Я заперечував проти того, щоб "Рядок був непомітивним, його слід створити так: String s = new String("Hello");", що невірно. Коротший варіант ( String s = "Hello";) є більш правильним через строкове інтернування.

2
З String, немає "більш правильного" варіанту. Обидва вірні. Хоча, як каже MichaelT, більш короткий варіант віддається перевазі через інтернатуру.
Андрес Ф.

1
@AndresF. Я змінив "менш правильний" на "менше ОО".
Тулен Кордова
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.