Установить и получить методы в java?

Как я могу использовать методы set и get и почему я должен их использовать? Они действительно полезны? А также можете ли вы привести примеры методов set и get?


person user759630    schedule 10.07.2011    source источник
comment
Вы спрашиваете о Java Bean.   -  person Rudy    schedule 10.07.2011
comment
Эта концепция, безусловно, не ограничивается Java-бинами.   -  person Erick Robertson    schedule 10.07.2011
comment
Вы можете прочитать некоторые из этих google.com/search?q=javabeans+tutorial 717 тысяч результатов.   -  person Peter Lawrey    schedule 10.07.2011
comment
Действительно? Вы, люди, смешны. Тот факт, что это очень простой вопрос, не означает, что вы должны отрицать каждый ответ. Вопрос, хотя и очень простой, полностью действителен и задан в контексте правил.   -  person ElGavilan    schedule 29.04.2014


Ответы (15)


Методы Set и Get — это шаблон инкапсуляции данных. Вместо прямого доступа к переменным-членам класса вы определяете get методы для доступа к этим переменным и set методы для их изменения. Инкапсулируя их таким образом, вы получаете контроль над общедоступным интерфейсом, если в будущем вам потребуется изменить внутреннюю работу класса.

Например, для переменной-члена:

Integer x;

У вас могут быть методы:

Integer getX(){ return x; }
void setX(Integer x){ this.x = x; }

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

person Justin Ethier    schedule 10.07.2011
comment
судя по всему, если бы я использовал методы set и get, было бы проще устранять ошибки? я прав? - person user759630; 10.07.2011
comment
Да, например, вы можете установить точки останова в этих методах, чтобы увидеть, когда остальная часть вашего кода попытается получить доступ к базовой переменной-члену. - person Justin Ethier; 10.07.2011
comment
то, что не упоминается в этом ответе, еще очень распространенный случай: если вы хотите разрешить доступ для чтения к полю только для любых иностранных классов - вы можете сделать это, только предоставив общедоступный метод получения и сохранив установщик закрытым или не предоставив установщик вообще. - person chiccodoro; 29.04.2014
comment
ваш пример также не показывает, как сеттер и геттер могут развиваться с течением времени (как вы указываете в тексте). - person chiccodoro; 29.04.2014
comment
Также обратите внимание, что вы можете выполнять проверку ошибок вместе с проверкой границ. - person mpop; 19.08.2014

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

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

private String taxId;

public void setTaxId(String taxId) {
    this.taxId = taxId;
}

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

private String taxId;

public void setTaxId(String taxId) throws IllegalArgumentException {
    if (isTaxIdValid(taxId)) {
        throw new IllegalArgumentException("Tax Id '" + taxId + "' is invalid");
    }
    this.taxId = taxId;
}

Следующим шагом для улучшения модульности программы является создание самого TaxId как объекта, способного проверять себя.

private final TaxId taxId = new TaxId()

public void setTaxId(String taxIdString) throws IllegalArgumentException {
    taxId.set(taxIdString); //will throw exception if not valid
}

Аналогично для геттера, что, если у нас еще нет значения? Может быть, мы хотим пойти другим путем, мы могли бы сказать:

public String getTaxId() throws IllegalStateException {
    return taxId.get(); //will throw exception if not set
}
person stivlo    schedule 10.07.2011
comment
-1 Первый пример великолепен. Убери всю улучшай модульность программной части и поменяю на +1. - person Erick Robertson; 10.07.2011
comment
На самом деле я согласен с Кентом Пью, как в книге Prefactoring: Treat String как примитивный тип данных. Описывайте атрибуты с помощью абстрактных типов данных, а не строк. -- Например, в типичном классе Customer может быть несколько таких абстрактных типов, а некоторые из них могут иметь сложные правила проверки, которые охватывают несколько строк кода (иногда сотни). Это именно то, что я сделал, я создал несколько таких типы данных, и они достаточно общие, чтобы я мог повторно использовать их в проектах. - person stivlo; 10.07.2011
comment
Я постараюсь объяснить это лучше. В объектно-ориентированной программе хороший способ мышления в классе может быть антропоморфным. Эксперт в предметной области, он должен делать что-то очень хорошо и только одно. Таким образом, класс Customer должен быть экспертом в области клиентов, а не в почтовых индексах, идентификаторах НДС, налоговых идентификаторах, муниципалитетах, и не должен знать, как должен быть отформатирован номер телефона. Все эти проблемы являются отдельными небольшими областями, и для каждой из них должен быть эксперт в этой области. Мы не хотим, чтобы этот код загрязнял наш основной класс. - person stivlo; 10.07.2011

Я думаю, вы хотите что-то вроде этого:

public class Person {

  private int age;

  //public method to get the age variable
  public int getAge(){
       return this.age
  }

  //public method to set the age variable
  public void setAge(int age){
       this.age = age;
  }
}

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

  public void setAge(int age){

       this.age = age;

       double averageCigarettesPerYear = this.smokedCigarettes * 1.0 / age;

       if(averageCigarettesPerYear >= 7300.0) {
           this.eventBus.fire(new PersonSmokesTooMuchEvent(this));
       }
  }

Конечно, это может быть опасно, если кто-то забудет вызвать setAge(int) там, где он должен, и установит age напрямую с помощью this.age.

person Stefan Falk    schedule 29.04.2014
comment
Это лучший способ сказать нет, который я когда-либо видел. - person Chris Rae; 05.02.2017

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

person Bohemian♦    schedule 10.07.2011

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

private String x;

public void setX(String newX) {
    if (newX == null) {
        x = "";
    } else {
        x = newX;
    }
}

public String getX() {
    if (x == null) {
        return "";
    } else {
       return x;
    }
}
person g051051    schedule 10.07.2011
comment
Интересно, поскольку x не может быть нулевым из-за setX, поэтому getX не нужно проверять на это. Но дело сделано, и любой, кто понимает этот комментарий, понимает всю суть геттеров и сеттеров. +1 - person Erick Robertson; 10.07.2011
comment
X будет нулевым, если getX вызывается перед вызовом setX. - person g051051; 10.07.2011
comment
Почему x просто не инициализируется ""? Затем вы сохраняете чек в getX. - person Erick Robertson; 10.07.2011
comment
Это, конечно, может быть и почти наверняка должно быть, но не обязательно. - person g051051; 10.07.2011

Некоторые преимущества использования геттеров и сеттеров (известных как encapsulation< /a> или data-hiding):

(первоначально ответил здесь)

<сильный>1. Поля класса можно сделать доступными только для чтения (предоставив только геттер) или только для записи (только предоставив установщик). Это дает классу полный контроль над тем, кто может получить доступ к его полям или изменить их.

Пример:

class EncapsulationExample {
    private int readOnly = -1;  // this value can only be read, not altered
    private int writeOnly = 0;    // this value can only be changed, not viewed
    public int getReadOnly() {
        return readOnly;
    }
    public int setWriteOnly(int w) {
        writeOnly = w;
    }
}

<сильный>2. Пользователям класса не нужно знать, как класс фактически хранит данные. Это означает, что данные отделены и существуют независимо от пользователей, что позволяет легче изменять и поддерживать код. Это позволяет сопровождающим вносить частые изменения, такие как исправление ошибок, улучшение дизайна и производительности, не влияя при этом на пользователей.

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

Пример (получение значения):

class EncapsulationExample {
    private int value;
    public int getValue() {     
        return value; // return the value
    }
}

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

class EncapsulationExample {
    private int value;
    public int getValue() {
        return value*2; // return twice the value
    }
}

<сильный>3. Делает код чище, читабельнее и легче для понимания.

Вот пример:

Без инкапсуляции:

class Box {
    int widthS; // width of the side
    int widthT; // width of the top
    // other stuff
}

// ...
Box b = new Box();
int w1 = b.widthS;  // Hm... what is widthS again? 
int w2 = b.widthT;  // Don't mistake the names. I should make sure I use the proper variable here!

С инкапсуляцией:

class Box {
    private int widthS; // width of the side
    private int widthT; // width of the top
    public int getSideWidth() {
        return widthS;
    }
    public int getTopWIdth() {
        return widthT;
    }
    // other stuff
}

// ...
Box b = new Box();
int w1 = b.getSideWidth(); // Ok, this one gives me the width of the side
int w2 = b.getTopWidth(); // and this one gives me the width of the top. No confusion, whew!

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

Вот good SO thread по этой теме.

Вот good read об инкапсуляции данных.

person nem035    schedule 16.10.2014
comment
почему бы не использовать лучшее имя переменной sideWidth, нужно быть отсталым, чтобы не понимать, что w1 = sideWidth; иметь в виду. - person SoyDuck; 30.03.2018
comment
@DuckSoy, этот пример тривиален, и его не следует принимать за чистую монету. Дело в общей идее отделения вашего собственного соглашения об именах и правил от пользователей вашего API. - person nem035; 30.03.2018

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

Проблема в том, что геттеры и сеттеры могут действовать как обходной путь для прямого доступа к закрытым данным. Частные данные называются частными, потому что они не предназначены для совместного использования с другими объектами; это означает представление состояния объекта. Предоставление другим объектам доступа к приватным полям объекта сводит на нет всю цель сделать его приватным в первую очередь. Более того, вы вводите связанность для каждого геттера или сеттера, который вы пишете. Рассмотрим это, например:

private String foo;

public void setFoo(String bar) {
    this.foo = bar;
}

Что произойдет, если где-то в будущем вы решите, что вам больше не нужен foo, или вы хотите сделать его целым? Каждый объект, использующий метод setFoo, теперь нужно изменить вместе с foo.

person xobicvap    schedule 09.07.2011

просто потому, что правило ООП: сокрытие данных и инкапсуляция. В большинстве случаев объявлять объект общедоступным и изменять его на лету — очень плохая практика. Также есть много других причин, но корень — инкапсуляция в ООП. и "купите книгу или идите читать по объектно-ориентированному программированию", вы все поймете по этому поводу после того, как прочитаете любую книгу по ООП.

person Ben Xu    schedule 10.07.2011

Преимущества методов get() set() заключаются в следующем.

  1. Вы можете легко сериализовать свой объект.
  2. Вы можете создать постоянный объект из содержащего класса.
  3. Вы можете легко преобразовать свойства в JSON.
  4. На уровне DAO (фреймворки, такие как Hibernate) вы можете напрямую сохранить объект в БД.
  5. Легкое понимание объектно-ориентированной концепции.
  6. Требуется во всех шаблонах дизайна, за исключением, возможно, шаблона с одним тоном.
  7. Безопасность для свойств, защищающих прямой доступ.
  8. Полиморфизм, инкапсуляция могут быть легко поняты и реализованы этим типом класса.

Пример:

private String personName;
private int personId;

    public void setPersonName(String name) throws Exception{
    if(!(name.equals("")||name=="")){
      this.personName = name;
    }
  }
  public String getPersonName(){
    return this.personName;
  }
  public void setPersonId(int id) throws Exception{
    this.personId = id;
  }
  public int getPersonId(){
    return this.personId;
  }
person Kaisar    schedule 10.07.2011
comment
что делает эта операция? я впервые сталкиваюсь с таким оператором name.equals() - person user759630; 11.07.2011

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

С объектами данных совершенно нормально не использовать геттеры и вместо этого использовать общедоступные поля. У них обычно нет сеттеров, так как они чаще всего неизменяемы - их поля устанавливаются через конструкторы, и никогда больше. Взгляните на Clean Code Боба Мартина или Pryce. и Growing OO Software... Фримана для получения подробной информации. .

person Urs Reupke    schedule 10.07.2011

public class Person{

private int age;

public int getAge(){
     return age;
}

public void setAge(int age){
     this.age = age;
}
}

Я думаю, это то, что вам нужно.. и это также называется pojo

person subash    schedule 29.04.2014

это код для метода set

public void setAge(int age){
  this.age = age;
}
person amit bhardwaj    schedule 29.04.2014

Похоже, вы пытаетесь сделать что-то похожее на C#, если вам нужен метод setAge create
setAge(int age){ this.age = age;}

person user3455363    schedule 29.04.2014

Я не вижу здесь простого ответа на второй вопрос (почему). Так вот.

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

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

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

person Madmenyo    schedule 26.08.2014

Этот ответ объединен с другим вопросом.

Ваш метод getAge() называется методом экземпляра в Java.

Чтобы вызвать метод экземпляра, у вас должен быть объект класса, в котором этот метод определен.

Например, если этот метод в классе называется Person, то

  1. Создайте объект Person, используя новый оператор

     Person p = new Person();
    
  2. Чтобы получить возраст объекта Person, используйте этот метод

    p.getAge()
    
person Abimaran Kugathasan    schedule 29.04.2014
comment
Проголосовали за секунду. Не знаю, как они оценивают. - person Abimaran Kugathasan; 29.04.2014