(не) Свойства в Java?

И така, съзнателно запазих Java n00b доскоро и първото ми истинско излагане доведе до лек шок: Java няма свойства на C# стил!

Добре, мога да живея с това. Мога също така да се закълна, че съм виждал код за получаване/задаване на свойства в Java в една кодова база, но не мога да си спомня къде. Как беше постигнато това? Има ли разширение за език за това? Свързано ли е с NetBeans или нещо подобно?


person Ishmaeel    schedule 16.09.2008    source източник


Отговори (14)


Съществува стандартен модел за гетери и сетери в Java, наречен Bean свойства. По принцип всеки метод, започващ с get, който не приема аргументи и връща стойност, е инструмент за получаване на свойство за свойство, наречено като останалата част от името на метода (с малка начална буква). По същия начин set създава сетер на метод void с един аргумент.

Например:

// Getter for "awesomeString"
public String getAwesomeString() {
  return awesomeString;
}

// Setter for "awesomeString"
public void setAwesomeString( String awesomeString ) {
  this.awesomeString = awesomeString;
}

Повечето Java IDE ще генерират тези методи за вас, ако ги помолите (в Eclipse е толкова просто, колкото да преместите курсора в поле и да натиснете Ctrl-1, след което да изберете опцията от списъка).

Колкото и да си струва, за четимост всъщност можете да използвате is и has вместо get и за свойства от булев тип, както в:

public boolean isAwesome();

public boolean hasAwesomeStuff();
person Calum    schedule 16.09.2008
comment
Мога да се закълна, че съм виждал синтаксиса на свойствата в стил C# някъде в някакъв Java код, но за живота си не мога да си спомня къде и как. Това наистина не отговаря на въпроса ми, но ще го приема заради фактора страхотност. Може би тогава съм халюцинирал. - person Ishmaeel; 16.09.2008
comment
Почти съм сигурен, че не може да се направи в Java, съжалявам. Има много JVM езици, които имат първокласна поддръжка за този вид неща, но може би това е, което видяхте? - person Calum; 16.09.2008
comment
Нарушение ли е на тази конвенция, ако поставите префикс на променлива член с нещо като m, m_ или _, но след това не включите този префикс в името на свойството? - person Panzercrisis; 03.09.2014

Изненадан съм, че никой не спомена project lombok

Да, в момента няма свойства в java. Има и някои други липсващи функции.
Но за щастие имаме project lombok, който се опитва да подобри ситуацията. Също така става все по-популярен всеки ден.

Така че, ако използвате lombok:

@Getter @Setter int awesomeInteger = 5;

Този код също ще генерира getAwesomeInteger и setAwesomeInteger. Така че е доста подобно на C# автоматично внедрени свойства.

Можете да получите повече информация относно гетерите и сетерите на Ломбок тук.
Определено трябва да разгледате други функции също. Моите любими са:

Lombok е добре интегриран с IDE, така че ще покаже генерирани методи, сякаш съществуват (предложения, съдържание на клас, отидете на декларация и рефакторинг).
Единственият проблем с lombok е, че други програмисти може да не знаят за него . Винаги можете да delombok кода, но това е по-скоро заобиколно решение, отколкото решение.

person Aleks-Daniel Jakimenko-A.    schedule 28.08.2013
comment
наличието на методи, които не можете да видите в кода, изглежда още по-лошо. Автоматичните свойства в c# всъщност са само половината от историята - става въпрос най-вече за именуване и групиране на свързана логика. - person JonnyRaa; 12.05.2014
comment
@JonnyLeeds добре, как изобщо е лошо? Можете да ги видите в кода, като забележите @Getter и @Setter анотации, и те се показват и в други ленти с инструменти (като контур или предложения) - person Aleks-Daniel Jakimenko-A.; 14.05.2014
comment
Анотациите не се наследяват - по този начин намаляват способността ви да правите обектно ориентирано разработване. Ако правите OO, тогава знаете, че има много малка причина дори да имате гетери и сетери. Много по-добре е да се изложи поведение, а не модел на данни. Ние сме далеч отвъд мястото, където някой трябва да използва структури (beans). - person Rodney P. Barbati; 14.11.2017

„Поддръжка на Java Property“ беше предложена за Java 7, но не влезе в езика.

Вижте http://tech.puredanger.com/java7#property за повече връзки и информация, ако заинтересовани.

person Cheekysoft    schedule 16.09.2008

Bean конвенцията е да се пише код по този начин:

private int foo;
public int getFoo() {
    return foo;
}
public void setFoo(int newFoo) {
    foo = newFoo;
}

В някои от другите езици на JVM, напр. Groovy, получавате свойства, които могат да бъдат заменени, подобни на C#, напр.

int foo

до който се осъществява достъп с обикновен .foo и използва реализации по подразбиране getFoo и setFoo, които можете да замените, ако е необходимо.

person Hank Gay    schedule 16.09.2008

public class Animal {

    @Getter @Setter private String name;
    @Getter @Setter private String gender;
    @Getter @Setter private String species;
}

Това е нещо като C# свойства. Това е http://projectlombok.org/

person dantuch    schedule 28.08.2013
comment
Трябва да се отбележи: това би се считало за езиково разширение и има тенденция да прави IDE много объркани. - person millimoose; 28.08.2013
comment
@millimoose Просто ви трябва плъгин за IDE. За съжаление всеки, който използва такъв код, има нужда от него. - person dantuch; 28.08.2013
comment
Нуждаете се от плъгин за IDE, което ме кара да навия вестник и да ударя човека, отговорен за него. (Въпреки че вероятно това е повече в случаите, когато конфигурацията на IDE е основната система за компилиране на кодова база.) - person millimoose; 28.08.2013

Може да не се нуждаете от префикси "get" и "set", за да изглежда повече като свойства, можете да го направите по следния начин:

public class Person {
    private String firstName = "";
    private Integer age = 0;

    public String firstName() { return firstName; } // getter
    public void firstName(String val) { firstName = val; } // setter

    public Integer age() { return age; } // getter
    public void age(Integer val) { age = val; } //setter

    public static void main(String[] args) {
        Person p = new Person();

        //set
        p.firstName("Lemuel");
        p.age(40);

        //get
        System.out.println(String.format("I'm %s, %d yearsold",
            p.firstName(),
            p.age());
    }
}
person LEMUEL ADANE    schedule 28.01.2015

Повечето IDE за Java автоматично ще генерират getter и setter код вместо вас, ако искате. Има няколко различни конвенции и IDE като Eclipse ще ви позволи да изберете коя искате да използвате и дори ще ви позволи да дефинирате своя собствена.

Eclipse дори включва автоматизиран рефакторинг, който ще ви позволи да обвиете свойство в getter и setter и ще промени целия код, който има директен достъп до свойството, за да го накара да използва getter и/или setter.

Разбира се, Eclipse може да модифицира само код, за който знае - всички външни зависимости, които имате, могат да бъдат нарушени от такова преработване.

person Bill Michell    schedule 16.09.2008

Моят опит с Java също не е толкова висок, така че всеки може да ме коригира. Но AFAIK, общата конвенция е да се напишат два метода така:

public string getMyString() {
    // return it here
}

public void setMyString(string myString) {
    // set it here
}
person Mark Embling    schedule 16.09.2008

От книгата на Джефри Рихтер CLR чрез C#: (Мисля, че това може да са причините свойствата все още да не се добавят в JAVA)

  • Метод на свойство може да хвърли изключение; полевият достъп никога не хвърля изключение.
  • Свойство не може да бъде предадено като out или ref параметър към метод; поле може.
  • Изпълнението на метод на свойство може да отнеме много време; достъпът до поле винаги завършва незабавно. Често срещана причина за използване на свойства е да се извърши синхронизиране на нишка, което може да спре нишката завинаги и следователно не трябва да се използва свойство, ако се изисква синхронизиране на нишка. В тази ситуация се предпочита метод. Също така, ако вашият клас може да бъде достъпен дистанционно (например вашият клас е извлечен от System.MarshalByRefObject), извикването на метода на свойството ще бъде много бавно и следователно методът е за предпочитане пред свойство. Според мен класовете, извлечени от MarshalByRefObject, никога не трябва да използват свойства.
  • Ако се извика няколко пъти подред, метод на свойство може да връща различна стойност всеки път; поле връща същата стойност всеки път. Класът System.DateTime има свойство Now само за четене, което връща текущите дата и час. Всеки път, когато правите заявка за това свойство, то ще върне различна стойност. Това е грешка и Microsoft желае те да могат да коригират класа, като направят Now метод вместо свойство. Свойството TickCount на Environment е друг пример за тази грешка.
  • Метод на собственост може да причини видими странични ефекти; полевият достъп никога не го прави. С други думи, потребителят на даден тип трябва да може да задава различни свойства, дефинирани от даден тип, във всеки ред, който той или тя избере, без да забелязва различно поведение в типа.
  • Метод на свойство може да изисква допълнителна памет или да върне препратка към нещо, което всъщност не е част от състоянието на обекта, така че модифицирането на върнатия обект няма ефект върху оригиналния обект; заявката за поле винаги връща препратка към обект, който гарантирано е част от състоянието на оригиналния обект. Работата със свойство, което връща копие, може да бъде много объркващо за разработчиците и тази характеристика често не е документирана.
person th1rdey3    schedule 26.12.2013
comment
Това е грешка и Microsoft желае да могат да поправят класа, като направят Now метод вместо свойство. Има ли някъде доказателства за това? Опитайте да замените свойствата на всички думи с методи getter и setter и прочетете отново. Текстът все пак трябва да е точен и затова намирам подобни аргументи за глупави. По мое мнение това е просто, че не разбирам какво е Property, следователно не ми харесва... Е, Property е просто приятелски синтаксис за getter и setter методи... Така че, ако не харесвате свойства , тогава също не би трябвало да харесвате geter и setter... - person Jens; 09.10.2017

Ако използвате eclipse, тогава той има възможностите за автоматично генериране на метода за получаване и настройка за вътрешните атрибути, това може да бъде полезен и спестяващ време инструмент.

person TK.    schedule 16.09.2008

Току-що пускам анотации на Java 5/6 и процесор за анотации, за да помогна за това.

Разгледайте http://code.google.com/p/javadude/wiki/Annotations

Документацията е малко олекотена в момента, но бързата справка трябва да разкрие идеята.

По принцип той генерира суперклас с getters/setter (и много други опции за генериране на код).

Примерен клас може да изглежда така

@Bean(properties = {
    @Property(name="name", bound=true),
    @Property(name="age,type=int.class)
})
public class Person extends PersonGen {
}

Има много повече налични проби и в генерирания код няма зависимости по време на изпълнение.

Изпратете ми имейл, ако го изпробвате и го намерите за полезен! -- Скот

person Scott Stanchfield    schedule 16.09.2008

В java няма ключова дума за свойство (както можете да я намерите в C#), най-близкият начин да имате 1 дума getter/setter е да направите като в C++:

public class MyClass
{
    private int aMyAttribute;
    public MyClass()
    {
        this.aMyAttribute = 0;
    }
    public void mMyAttribute(int pMyAttributeParameter)
    {
        this.aMyAttribute = pMyAttributeParameter;
    }
    public int mMyAttribute()
    {
        return this.aMyAttribute;
    }
}
//usage :
int vIndex = 1;
MyClass vClass = new MyClass();
vClass.mMyAttribute(vIndex);
vIndex = 0;
vIndex = vClass.mMyAttribute();
// vIndex == 1
person Patrick PIGNOL    schedule 17.02.2018

Както бе споменато по-рано за eclipse, интегрираната среда за разработка (IDE) често може автоматично да създава методи за достъп.

Можете също да го направите с помощта на NetBeans.

За да създадете методи за достъп за вашия клас, отворете файл с клас, след това щракнете с десния бутон някъде в редактора на изходния код и изберете командата от менюто Refactor, Encapsulate Fields. Отваря се диалогов прозорец. Щракнете върху Избор на всички, след което щракнете върху Рефакторинг. Ето,

Късмет,

person Mario Levesque    schedule 06.01.2019

За мен проблемът е два:

  1. Всички тези допълнителни методи {get*/set*} претрупват кода на класа.
  2. НЕ можете да ги третирате като свойства:
    public class Test {
      private String _testField;

      public String testProperty {
       get {
        return _testField;
       }
       set {
        _testField = value;
       }
      }
    }

    public class TestUser {
      private Test test;

      public TestUser() {
        test = new Test();

        test.testProperty = "Just something to store";
        System.out.printLn(test.testProperty);
      }
    }

Това е лесната задача, която бих искал да използвам отново. НЕ се налага да използвате синтаксис за извикване на „метод“. Може ли някой да даде някои отговори какво се случи с Java?

Мисля, че проблемът е и в ненужното претрупване в кода, а не в „трудността“ при създаването на сетери/гетери. Смятам ги за грозен код. Харесвам това, което има C#. Не разбирам съпротивата срещу добавянето на тази възможност към Java.

Текущото ми решение е да използвам „публични“ членове, когато защитата не е необходима:

public class IntReturn {
    public int val;
}

public class StringReturn {
    public String val;
}

Те ще бъдат използвани за връщане на стойност от, да речем, ламбда:

StringReturn sRtn = new StringReturn()

if(add(2, 3, sRtn)){
    System.out.println("Value greater than zero");
}

public boolean add(final int a, final int b, final StringReturn sRtn){
    int rtn = a + b;
    sRtn.val = "" + rtn;
    return rtn > 0; // Just something to use the return for.
}

Също така наистина не обичам да използвам извикване на метод за задаване или получаване на вътрешна стойност от клас.

Ако вашата информация се прехвърля като „неизменна“, тогава новият запис на Java може да бъде решение. Въпреки това, той все още използва методологията setter/getter, само без префиксите set/get.

person Bradley Willcott    schedule 28.11.2019