Структурировать как объекты в Java

195

Это полностью противоречит способу Java создавать объекты, подобные структуре?

class SomeData1 {
    public int x;
    public int y;
}

Я вижу класс с аксессорами и мутаторами, более похожими на Java.

class SomeData2 {
    int getX();
    void setX(int x);

    int getY();
    void setY(int y);

    private int x;
    private int y;
}

Класс из первого примера удобен для обозначения.

// a function in a class
public int f(SomeData1 d) {
    return (3 * d.x) / d.y;
}

Это не так удобно.

// a function in a class
public int f(SomeData2 d) {
    return (3 * d.getX()) / d.getY();
}
Крис де Врис
источник
9
Вместо общедоступных изменяемых полей рассмотрим либо общедоступные неизменяемые поля, либо локальные изменяемые поля пакета. Либо было бы лучше ИМХО.
Питер Лори
Помните, что, хотя методы получения и установки ужасны / многословны, это своего рода сердце Java. Это не лаконичный язык. С другой стороны, вы НИКОГДА не должны вводить что-либо из этого, так как это то, что ваша IDE делает для вас. В динамическом языке вы должны печатать меньше, но вы должны печатать (обычно, хотя IDE могут помочь).
Дэн Розенстарк
По иронии судьбы, хотя ОО имеет свои сильные стороны с точки зрения инкапсуляции, это цена, которую нужно платить ЦП и хранилищу. Сборщик мусора (почти полностью) устраняет необходимость беспокоиться о том, когда следует удалять ссылки на объекты. Нынешняя тенденция проходит полный круг, используя C-подобные структуры вне кучи. Это идеально подходит для решений типа кэширования, межпроцессного взаимодействия, более быстрых операций с интенсивным использованием памяти, более низкой GC о / ч и может даже выиграть от более низкой о / ч памяти для ваших наборов данных. Если вы знаете, что делаете, вы бы не задавали этот вопрос ... так что подумайте еще раз!
user924272
@ user924272: Re "Текущий тренд проходит полный круг, используя C-подобные структуры вне кучи". Что бы вы сделали в Java, как ??? ИМХО, это область, где Java показывает свой возраст ...
ToolmakerSteve
@ ToolmakerSteve -Я вижу круг. Я не один. Такие компании, как Azul, заинтересованы в сборке мусора без пауз. Ява старая Правда. Инженеры, которые замечают слабость и что-то с этим делают, а не стонут? Они заслуживают уважения! +10 к
Азулу

Ответы:

62

Это часто обсуждаемая тема. Недостаток создания открытых полей в объектах заключается в том, что вы не можете контролировать значения, которые для него установлены. В групповых проектах, где много программистов используют один и тот же код, важно избегать побочных эффектов. Кроме того, иногда лучше возвращать копию объекта поля или каким-либо образом трансформировать его и т. Д. Вы можете высмеивать такие методы в своих тестах. Если вы создадите новый класс, вы можете не увидеть все возможные действия. Это похоже на защитное программирование - когда-нибудь получатели и установщики могут оказаться полезными, и их создание / использование не требует больших затрат. Поэтому они иногда полезны.

На практике большинство полей имеют простые методы получения и установки. Возможное решение будет выглядеть так:

public property String foo;   
a->Foo = b->Foo;

Обновление: маловероятно, что поддержка свойств будет добавлена ​​в Java 7 или, возможно, когда-либо. Другие языки JVM, такие как Groovy, Scala и т. Д., Поддерживают эту функцию сейчас. - Алекс Миллер

Бартош Берковский
источник
28
Это очень плохо, мне нравятся свойства стиля C # (что звучит как то, о чем вы говорите)
Джон Онстотт,
2
Так что используйте перегрузку ... private int _x; public void x (int value) {_x = значение; } public int x () {return _x; }
Гордон
12
Я предпочитаю использовать =, что, на мой взгляд, делает код чище.
Свиш
6
@ T-Bull: То, что вы МОЖЕТЕ иметь xдве разные вещи, не делает это хорошей идеей. ИМХО, это плохое предположение, поскольку оно может привести к путанице среди читателей. Основной принцип: не заставляйте читателя делать двойной дубль; сделайте очевидным то, что вы говорите - используйте разные имена для разных сущностей. Даже если разница заключается только в том, чтобы добавить подчеркивание. Не полагайтесь на пунктуацию, чтобы различать объекты.
ToolmakerSteve
2
@ToolmakerSteve: Это «может привести к путанице» является наиболее распространенным и все же самым слабым аргументом, когда речь идет о защите догмы кодирования (в отличие от стиля кодирования). Всегда есть кто-то, кто МОЖЕТ быть смущен простейшими вещами. Вы всегда можете найти кого-то, кто жаловался на то, что он допустил ошибку после того, как бодрствовал и писал код в течение половины недели или около того, а затем обвинял в вводящем в заблуждение стиле кодирования. Я не позволяю этому рассчитывать. Этот стиль действителен, очевиден и сохраняет пространство имен в чистоте. Кроме того, здесь нет разных сущностей, есть / one / entity и некоторый шаблонный код вокруг него.
T-Bull
290

Похоже, что многие Java-люди не знакомы с Sun Java Coding Guidelines, в которых говорится, что вполне целесообразно использовать общедоступную переменную экземпляра, когда класс по сути является «Struct», если Java поддерживает «struct» (когда нет поведения).

Люди склонны думать, что геттеры и сеттеры - это способ Java, как будто они лежат в основе Java. Это не так. Если вы следуете руководству Sun Java Coding Guidelines, используя общедоступные переменные экземпляра в соответствующих ситуациях, вы на самом деле пишете лучший код, чем загромождаете его ненужными средствами получения и установки.

Соглашения Java Code от 1999 и до сих пор без изменений.

10.1 Предоставление доступа к переменным экземпляра и класса

Не делайте ни один экземпляр или переменную класса общедоступным без уважительной причины. Часто переменные экземпляра не нужно явно устанавливать или получать часто, что происходит как побочный эффект вызовов методов.

Одним из примеров соответствующих общедоступных переменных экземпляра является случай, когда класс по сути является структурой данных без какого-либо поведения. Другими словами, если бы вы использовали структуру вместо класса (если Java поддерживает структуру), то целесообразно сделать переменные экземпляра класса общедоступными .

http://www.oracle.com/technetwork/java/javase/documentation/codeconventions-137265.html#177

http://en.wikipedia.org/wiki/Plain_old_data_structure

http://docs.oracle.com/javase/1.3/docs/guide/collections/designfaq.html#28

developer.g
источник
88
+1 За фактический авторитетный источник. Любой другой ответ - люди раскручивают свое мнение, как факты.
ArtOfWarfare
1
Существует спецификация Java Beans, которая является стандартным способом доступа к свойствам с использованием методов get и set ... см. Обзор в en.wikipedia.org/wiki/JavaBeans .
user924272
4
@ user924272: Как спецификация Java Beans относится к этому ответу, в котором обсуждается, когда уместно использовать «общедоступные переменные экземпляра»? Если бы спецификация была стандартным способом автоматического превращения переменных экземпляра в свойства, в частности C #, это могло бы быть уместно. Но это не так, верно? Он просто определяет наименования шаблонных геттеров и сеттеров, которые должны быть созданы для создания такого отображения.
ToolmakerSteve
@ToolmakerSteve. Это вопрос Java. Кроме того, этот вопрос позволяет избежать общей проблемы, когда существует спецификация. С точки зрения старой школы, гораздо проще отлаживать полевые мутации, когда есть стандартный способ сделать это - установить точку останова в установщике. Это, вероятно, устарело в современных отладчиках, но я вынужден нахмуриться с классами, которые напрямую «пробивают» объекты ... хотя это нормально для небольших приложений, это настоящая головная боль для больших приложений и крупных организаций
user924272
223

Используйте здравый смысл на самом деле. Если у вас есть что-то вроде:

public class ScreenCoord2D{
    public int x;
    public int y;
}

Тогда нет смысла заключать их в геттеры и сеттеры. Вы никогда не будете хранить координаты x, y в целых пикселях другим способом. Геттеры и сеттеры только замедляют вас.

С другой стороны, с:

public class BankAccount{
    public int balance;
}

Возможно, вы захотите изменить способ расчета баланса в какой-то момент в будущем. Это должно действительно использовать геттеры и сеттеры.

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

IZB
источник
3
Я согласен с этим ответом и скажу далее, что вы можете создать класс с открытыми полями, если поля выделены жирным шрифтом независимо друг от друга. т.е. одно поле не зависит от другого. Это может быть весьма полезно во многих случаях, для множественных возвращаемых значений из функции или для полярных коодинатов. {угол, длина}, которые идут вместе, но никак не зависят друг от друга.
Спейсен Джассет
@SpacenJasset: к вашему сведению, я не вижу, как ваши примеры (множественные возвращаемые значения; полярные координаты) имеют какое-либо отношение к использованию открытых полей по сравнению с методами получения / установки. В случае множественных возвращаемых значений это может быть даже контрпродуктивно, поскольку, возможно, вызывающая сторона должна только ПОЛУЧИТЬ возвращаемые значения, что свидетельствует в пользу общедоступных и частных установщиков (неизменяемых). Это также может быть верно для возврата полярных координат из объекта (x, y) - рассмотрим АККУМУЛЯЦИОННЫЕ математические ошибки, поскольку изменения отдельных компонентов полярных координат преобразуются обратно в (x, y).
ToolmakerSteve
@SpacenJasset: Но я согласен с вашим принципом.
ToolmakerSteve
1
У вас есть правильная точка, но я чувствую, что пиксели - это плохой пример, потому что убедиться, что пиксель находится внутри окна (просто пример), это то, что кто-то может сделать, и, кроме того, позволить кому-то установить пиксель, чтобы он (-5, -5)не был хорошая идея. :-)
Хорси
50

Для решения проблем изменчивости вы можете объявить x и y как final. Например:

class Data {
  public final int x;
  public final int y;
  public Data( int x, int y){
    this.x = x;
    this.y = y;
  }
}

Вызывающий код, который пытается записать в эти поля, получит ошибку времени компиляции: «поле x объявлено окончательным; его нельзя назначить».

В этом случае код клиента может иметь удобство «быстрого доступа», которое вы описали в своем посте.

public class DataTest {
    public DataTest() {
        Data data1 = new Data(1, 5);
        Data data2 = new Data(2, 4);
        System.out.println(f(data1));
        System.out.println(f(data2));
    }

    public int f(Data d) {
        return (3 * d.x) / d.y;
    }

    public static void main(String[] args) {
        DataTest dataTest = new DataTest();
    }
}
Брайан
источник
3
Спасибо - ответ, который полезен и лаконичен. Показывает, как получить преимущество полевого синтаксиса, когда не требуется изменчивость.
ToolmakerSteve
@ToolmakerSteve - спасибо за отзыв - высоко ценится.
Брайан
Я попытался использовать конечные экземпляры конечного класса с конечными полями в качестве структуры «экземпляры», но в caseвыражении, ссылающемся на такое поле экземпляра, я получил Case expressions must be constant expressions. как обойти это? какая здесь идиоматическая концепция?
n611x007
1
Поля final по-прежнему являются ссылками на объекты, которые не являются константами, поскольку они будут инициализированы при первом использовании класса. Компилятор не может знать «значение» ссылок на объекты. Константы должны быть известны при компиляции.
Йохан Тиден
1
+1 Действительно важный ответ. Полезность неизменяемых классов нельзя недооценивать, на мой взгляд. Их семантика «запускай и забывай» часто упрощает рассуждения о коде, особенно в многопоточных средах, где они могут быть произвольно распределены между потоками без синхронизации.
Оператор
11

Не используй public поля

Не используйте publicполя, если вы действительно хотите обернуть внутреннее поведение класса. Взять java.io.BufferedReaderк примеру. Имеет следующее поле:

private boolean skipLF = false; // If the next character is a line feed, skip it

skipLFчитается и пишется во всех методах чтения. Что если внешний класс, работающий в отдельном потоке, злонамеренно изменил состояние skipLFв середине чтения? BufferedReaderобязательно сойду с ума.

Используй publicполя

Возьмите этот Pointкласс, например:

class Point {
    private double x;
    private double y;

    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }

    public double getX() {
        return this.x;
    }

    public double getY() {
        return this.y;
    }

    public void setX(double x) {
        this.x = x;
    }

    public void setY(double y) {
        this.y = y;
    }
}

Это сделает расчет расстояния между двумя точками очень болезненным для написания.

Point a = new Point(5.0, 4.0);
Point b = new Point(4.0, 9.0);
double distance = Math.sqrt(Math.pow(b.getX() - a.getX(), 2) + Math.pow(b.getY() - a.getY(), 2));

Класс не имеет никакого поведения, кроме простых методов получения и установки. Допустимо использовать открытые поля, когда класс представляет собой просто структуру данных, не имеет и никогда не будет иметь поведения (тонкие методы получения и установки не рассматриваются здесь). Это можно записать лучше так:

class Point {
    public double x;
    public double y;

    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }
}

Point a = new Point(5.0, 4.0);
Point b = new Point(4.0, 9.0);
double distance = Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2));

Чистота!

Но помните: не только в вашем классе должно отсутствовать поведение, но также не должно быть причин иметь поведение в будущем.


(Это именно то, что описывает этот ответ . Цитировать «Соглашения о коде для языка программирования Java: 10. Практика программирования») :

Одним из примеров соответствующих общедоступных переменных экземпляра является случай, когда класс по сути является структурой данных без какого-либо поведения. Другими словами, если бы вы использовали structкласс вместо (если поддерживается Java struct), то целесообразно сделать переменные экземпляра класса общедоступными.

Таким образом, официальная документация также принимает эту практику.)


Кроме того, если вы уверены, что члены вышеупомянутого Pointкласса должны быть неизменяемыми, вы можете добавить finalключевое слово, чтобы обеспечить его выполнение:

public final double x;
public final double y;
sampathsris
источник
8

Кстати, структура, которую вы даете в качестве примера, уже существует в библиотеке базовых классов Java как java.awt.Point. У него есть x и y в качестве открытых полей, проверьте сами .

Если вы знаете, что делаете, и другие в вашей команде знают об этом, тогда можно использовать открытые поля. Но вы не должны полагаться на это, потому что они могут вызвать головную боль, как в ошибках, связанных с разработчиками, использующими объекты, как если бы они были структурами, размещенными в стеке (объекты Java всегда отправляются методам как ссылки, а не как копии).

Spoike
источник
+1 Хорошее упоминание о проблеме - способ, которым результат все еще НЕ похож на структуру C. Однако проблема, которую вы поднимаете о том, что java-объекты всегда являются ссылками, не улучшается созданием сеттера вместо наличия открытого для записи поля (что является сутью вопроса OP - какое представление использовать). Скорее, это аргумент в пользу того, чтобы делать НИЧЕГО. Это аргумент в пользу НЕМНОГОСТОЙКОСТИ. Что может быть сделано как public finalполе, как в ответе Брайана, или с помощью публичного получателя, но без публичного установщика. То есть, неважно, использует ли человек поля или методы доступа.
ToolmakerSteve
8

Re: аку, изб, Джон Топли ...

Остерегайтесь проблем изменчивости ...

Может показаться разумным не использовать геттеры / сеттеры. Это на самом деле может быть хорошо в некоторых случаях. Реальная проблема с предложенным шаблоном, показанным здесь, является изменчивостью.

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

Плохо, когда этот объект является важной частью внутреннего состояния другого, вы только что раскрыли внутреннюю реализацию. Чтобы предотвратить это, вместо этого должна быть возвращена копия объекта. Это работает, но может вызвать огромное давление GC из-за тонны созданных одноразовых копий.

Если у вас есть открытые поля, рассмотрите возможность сделать класс доступным только для чтения. Добавьте поля в качестве параметров в конструктор и отметьте поля как окончательные. В противном случае убедитесь, что вы не выставляете внутреннее состояние, и если вам нужно создать новые экземпляры для возвращаемого значения, убедитесь, что оно не будет вызываться чрезмерно.

См .: « Эффективная Ява » Джошуа Блоха - Пункт № 13: Неизменность в пользу.

PS: Также имейте в виду, что все JVM в эти дни будут оптимизировать getMethod, если это возможно, в результате всего лишь одна инструкция чтения поля.

Марк Ренуф
источник
12
Как получатель / установщик решает эту проблему. У вас все еще есть ссылка, у вас нет синхронизации с операциями. Получатели / установщики не обеспечивают защиту сами по себе.
he_the_great
1
Получатели и установщики могут обеспечить синхронизацию при необходимости. Вы также ожидаете, что геттеры и сеттеры будут делать гораздо больше, чем они должны были делать. Независимо от этого, проблема синхронизации все еще остается.
user924272
7

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

Как уже отмечалось выше, есть 2 проблемы, с которыми вы сталкиваетесь, и они не могут быть исправлены:

  • Практически любой автоматизированный инструмент в мире Java основан на соглашении getter / setter. То же самое, как отмечали другие, jsp-теги, конфигурация пружин, инструменты затмения и т. Д. И т. Д. ... Борьба с тем, что ожидают увидеть ваши инструменты, - это рецепт для длинных сессий, троллящих через Google, пытающихся найти этот нестандартный способ инициации. весенние бобы. На самом деле не стоит беспокоиться.
  • Если у вас есть элегантно закодированное приложение с сотнями общедоступных переменных, вы, вероятно, обнаружите хотя бы одну ситуацию, в которой их недостаточно - когда вам абсолютно необходима неизменность, или вам нужно вызвать какое-то событие, когда переменная будет установлена, или вы хотите выбросить исключение при изменении переменной, потому что оно устанавливает состояние объекта в нечто неприятное. Затем вы застряли с незавидным выбором между загромождением вашего кода каким-либо специальным методом везде, где есть прямая ссылка на переменную, имея специальную форму доступа для 3 из 1000 переменных в вашем приложении.

И это в лучшем случае сценарий работы полностью в частном частном проекте. Как только вы экспортируете все это в общедоступную библиотеку, эти проблемы станут еще больше.

Ява очень многословна, и это заманчиво. Не делай этого.

Стив Б.
источник
Отличная дискуссия о проблемах перехода на общественные поля. Определенный недостаток Java, который раздражает меня, когда мне приходится переключаться обратно на Java из C # (что было извлечено из неудобств Java здесь).
ToolmakerSteve
4

Если путь Java - это путь OO, то да, создание класса с открытыми полями нарушает принципы сокрытия информации, которые говорят, что объект должен управлять своим собственным внутренним состоянием. (Так как я не просто излагаю на вас жаргон, преимущество сокрытия информации заключается в том, что внутренняя работа класса скрыта за интерфейсом - скажем, вы хотели изменить механизм, с помощью которого ваш класс struct сохранил одно из своих полей, вам, вероятно, придется вернуться и изменить любые классы, которые используют класс ...)

Вы также не можете воспользоваться поддержкой классов, совместимых с именами JavaBean, что может повредить, если вы решите, скажем, использовать класс на странице JavaServer, написанной с использованием языка выражений.

Статья JavaWorld « Почему методы Getter и Setter являются злом» также может быть интересна для размышления о том, когда не следует реализовывать методы accessor и mutator.

Если вы пишете небольшое решение и хотите минимизировать объем используемого кода, способ Java может быть неправильным - я думаю, это всегда зависит от вас и проблемы, которую вы пытаетесь решить.

brabster
источник
1
+1 за ссылку на статью «Почему методы получения и установки являются злыми». Тем не менее, ваш ответ был бы более ясным, если бы вы указали, что ОБА открытые поля И общедоступные методы получения / установки РАВНО НЕ являются способом Java: как объяснено в этой статье - когда это возможно, не делайте и то и другое. Вместо этого предоставьте клиентам методы, специфичные для того, что им нужно делать, вместо того, чтобы отражать внутреннее представление экземпляра. ОДНАКО, на самом деле это не относится к задаваемому вопросу (который следует использовать для простого случая "struct"), на который лучше отвечают developer.g, izb и Brian.
ToolmakerSteve
3

В этом типе кода нет ничего плохого, если автор знает, что они являются структурами (или шаттлами данных), а не объектами. Многие Java-разработчики не могут отличить правильно сформированный объект (не просто подкласс java.lang.Object, но настоящий объект в определенной области) и ананас. Поэтому они в конечном итоге пишут структуры, когда им нужны объекты и наоборот.

luis.espinal
источник
ананас рассмешил меня :)
Гийом
Однако этот ответ ничего не говорит о том, что это за разница. Обман на неквалифицированных разработчиков не помогает тем разработчикам знать, когда создавать структуру, а когда создавать класс.
ToolmakerSteve
Это ничего не говорит о разнице, потому что автор знает о разнице (он знает, что такое структуроподобная сущность). Автор спрашивает, подходит ли использование структур на языке OO, и я отвечаю «да» (в зависимости от проблемной области). Если бы вопрос был о том, что делает объект реальным объектом домена, то у вас была бы возможность встать на ноги аргумент.
luis.espinal
Кроме того, единственным типом неквалифицированного разработчика, который не должен знать разницу, будет тот, который все еще находится в школе. Это чрезвычайно важно, например, знать разницу между связанным списком и хеш-таблицей. Если человек заканчивает учебу с 4-летним дипломом по программному обеспечению, не зная, что такое настоящий предмет, то или этот человек не подходит для этой карьеры, или он / она должен вернуться в школу и потребовать возмещение. Я серьезно.
luis.espinal
Но чтобы удовлетворить вашу жалобу, я предоставлю ответ (который имеет мало общего с исходным вопросом и заслуживает отдельной темы). Объекты имеют поведение и инкапсулируют состояние. Структуры нет. Объекты являются государственными машинами. Структуры предназначены только для агрегирования данных. Если люди хотят получить более подробный ответ, они могут создать новый вопрос, в котором мы сможем развить его до глубины души.
luis.espinal
2

Проблема с использованием доступа к общедоступным полям та же, что и при использовании нового вместо заводского метода - если вы передумаете позже, все существующие вызывающие абоненты будут прерваны. Таким образом, с точки зрения развития API, обычно неплохо кусать пули и использовать методы получения / установки.

Одно место, куда я иду другим путем, - это когда вы строго контролируете доступ к классу, например, во внутреннем статическом классе, используемом в качестве внутренней структуры данных. В этом случае может быть гораздо понятнее использовать полевой доступ.

Кстати, по утверждению e-bartek, очень маловероятно, что IMO будет добавлена ​​поддержка свойств в Java 7.

Алекс Миллер
источник
1
Это правда, но если вы используете Java, это не проблема, поскольку вы можете выполнить рефакторинг всей кодовой базы в один клик (Eclipse, Netbeans, возможно, VIM и Emacs). Если вы выбрали одного из его динамичных друзей, таких как Groovy, даже простая инкапсуляция может привести к исправлению в течение нескольких часов или дней. К счастью, у вас есть свои тесты, которые сообщат вам ... сколько еще кода вы должны исправить.
Дэн Розенстарк
2
Конечно, вы предполагаете, что все пользователи находятся в вашей базе кода, но, конечно, это часто не так. Часто по различным нетехническим причинам невозможно даже изменить код, который может быть в вашей собственной кодовой базе.
Алекс Миллер
2

Я часто использую этот шаблон при создании закрытых внутренних классов, чтобы упростить мой код, но я бы не рекомендовал выставлять такие объекты в публичном API. В общем, чем чаще вы можете сделать объекты в вашем публичном API неизменяемыми, тем лучше, и невозможно создать свой «структурный» объект неизменным образом.

Кроме того, даже если бы я писал этот объект как частный внутренний класс, я все равно предоставлял бы конструктор, чтобы упростить код для инициализации объекта. Необходимость иметь 3 строки кода, чтобы получить пригодный для использования объект, когда это будет сделано, просто беспорядок.

Крис Наттикомб
источник
2

Очень-очень старый вопрос, но позвольте мне сделать еще один небольшой вклад. Java 8 представила лямбда-выражения и ссылки на методы. Лямбда-выражения могут быть простыми ссылками на методы и не объявлять «истинное» тело. Но вы не можете «преобразовать» поле в ссылку на метод. таким образом

stream.mapToInt(SomeData1::x)

не законно, но

stream.mapToInt(SomeData2::getX)

является.

Любомир Шайдаров
источник
В этом случае вы можете использовать data -> data.x, что все еще разумно
Джеймс Краус
1

Я не вижу вреда, если вы знаете, что это всегда будет простая структура и что вы никогда не захотите привязывать к ней поведение.

Джон Топли
источник
1

Это вопрос объектно-ориентированного проектирования, а не языка Java. Обычно рекомендуется скрывать типы данных внутри класса и предоставлять только те методы, которые являются частью API класса. Если вы выставите внутренние типы данных, вы никогда не сможете изменить их в будущем. Если вы их скрываете, ваше единственное обязательство перед пользователем - это метод return и типы аргументов.

Джонатан
источник
1

Здесь я создаю программу для ввода имени и возраста 5 разных людей и выполняю сортировку по возрасту. Я использовал класс, который действует как структура (например, язык программирования C), и основной класс для выполнения всей операции. Ниже я предоставляю код ...

import java.io.*;

class NameList {
    String name;
    int age;
}

class StructNameAge {
    public static void main(String [] args) throws IOException {

        NameList nl[]=new NameList[5]; // Create new radix of the structure NameList into 'nl' object
        NameList temp=new NameList(); // Create a temporary object of the structure

        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

        /* Enter data into each radix of 'nl' object */

        for(int i=0; i<5; i++) {
            nl[i]=new NameList(); // Assign the structure into each radix

            System.out.print("Name: ");
            nl[i].name=br.readLine();

            System.out.print("Age: ");
            nl[i].age=Integer.parseInt(br.readLine());

            System.out.println();
        }

        /* Perform the sort (Selection Sort Method) */

        for(int i=0; i<4; i++) {
            for(int j=i+1; j<5; j++) {
                if(nl[i].age>nl[j].age) {
                    temp=nl[i];
                    nl[i]=nl[j];
                    nl[j]=temp;
                }
            }
        }

        /* Print each radix stored in 'nl' object */

        for(int i=0; i<5; i++)
            System.out.println(nl[i].name+" ("+nl[i].age+")");
    }
}

Приведенный выше код не содержит ошибок и протестирован ... Просто скопируйте и вставьте его в свою IDE и ... Вы знаете и что ??? :)

Авик Кумар Госвами
источник
0

Вы можете создать простой класс с открытыми полями и без методов в Java, но он по-прежнему является классом и все еще обрабатывается синтаксически и с точки зрения распределения памяти, как класс. Нет способа по-настоящему воспроизвести структуры в Java.

cblades
источник
0

Иногда я использую такой класс, когда мне нужно вернуть несколько значений из метода. Конечно, такой объект недолговечный и с очень ограниченной видимостью, так что все должно быть в порядке.

PhiLho
источник
0

Как и в большинстве случаев, есть общее правило, а затем есть конкретные обстоятельства. Если вы делаете закрытое захваченное приложение, чтобы знать, как будет использоваться данный объект, вы можете воспользоваться большей свободой, чтобы улучшить видимость и / или эффективность. Если вы разрабатываете класс, который будет использоваться публично другими, не зависящими от вас, тогда склоняйтесь к модели получателя / установщика. Как и во всем, просто используйте здравый смысл. Часто нормально провести начальный раунд с публикой, а затем поменять их на геттер / сеттеры.

Evvo
источник
0

Аспектно-ориентированное программирование позволяет вам перехватывать назначения или выборки и присоединять к ним перехватывающую логику, которая, как я предлагаю, является правильным способом решения проблемы. (Вопрос о том, должны ли они быть публичными, защищенными или защищенными пакетами, является ортогональным.)

Таким образом, вы начинаете с неперехваченных полей с правильным квалификатором доступа. Когда требования к вашей программе растут, вы присоединяете логику для проверки, делаете копию возвращаемого объекта и т. Д.

Философия получения / установки устанавливает затраты на большое количество простых случаев, когда они не нужны.

Является ли аспектный стиль чище или нет, это несколько качественно. Мне было бы легко видеть только переменные в классе и просматривать логику отдельно. Фактически, смыслом для Apect-ориентированного программирования является то, что многие проблемы являются сквозными, и разделение их на части в самом теле класса не является идеальным (регистрация в качестве примера - если вы хотите регистрировать все, получает от Java то, чего вы хотите) написать целую кучу геттеров и синхронизировать их, но AspectJ позволяет вам использовать одну строку).

Вопрос IDE - это красная сельдь. Это не столько печатание, сколько чтение и визуальное загрязнение, возникающее из-за get / sets.

На первый взгляд аннотации похожи на аспектно-ориентированное программирование, однако они требуют от вас исчерпывающего перечисления pointcut, добавляя аннотации, в отличие от краткой спецификации подстановки точек в AspectJ.

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

некромант
источник