Java language convention; getters/setters

2019-07-15 07:14发布

问题:

Public class Example {

    private int number;

    public Example(int number){
        this.number = number;
    }

    public int getNumber(){
        return number;
    }

    public void setNumber(int number){
        this.number = number;
    }

    public static void main(String[] args){
        Example e = new Example(5);

What is preffered when accessing a variable within its own class; "e.number" or "e.getNumber()" ?

Edit:
I think the most important question is: does the compiler know the method you call is a getter or setter. So, will e.setNumber(5); be as fast as e.number = 5;

回答1:

I would say it depends on the situation. If the field is something simple such as an int and unlikely to change in the future, I would access it using number and not getNumber().

If the field represents something more involved that could in some situation perhaps be computed in future situation or possibly overridden in a subclass, getNumber() is the obvious choice.

My rule of thumb: If there is any remote chance that I can benefit from going through getNumber() I use getNumber(), otherwise I use number for clarity and brevity.



回答2:

e.getNumber() is the common approach. So get or set + VariableName.

You could also have a look HERE.



回答3:

this.number

In most cases they will be optimized to the same code but the point of using setters/getters is to avoid changin API in case of change of implementation. However in class you don't use "API" but you see all the internals and state.

Additionally you can use

numer += 5;

instead of

setNumber(getNumber() + 5);

Edit: Of course outside class it shoudl be protected by getter/setter as you may change internal representation and you can provide backward-compatibility by reimplementing them in terms of new state representation.

Edit 2: main is a bit special. I'd say that main should be as minimal as possible - create some objects and call one or two methods maximum - hence it should not assign variebles and should be threated as 'external' part. On the other hand some provides tests methods in main which may require accessing state directly. So if you can you should not directly access fields in main.

As of speed in main it does not matter anyway as starting the JVM would offset any costs. The real difference would be in the inner loops in which JIT would take care about it.



回答4:

There will only be a difference if the getter/setter does something extra. If you know from the start this will be the case, then use the methods even within the class. If not I'd just go with the direct field manipulation and rely on Eclipse to help me with the refactoring later if necessary.



回答5:

To answer your last question, look at this example,

Java Code:

public void test2() {
    setNumber(getNumber() + 1);
}

Byte Code:

public test2()V
   L0
    LINENUMBER 47 L0
    ALOAD 0
    ALOAD 0
    INVOKEVIRTUAL com/test/ByteCodeTester.getNumber()I
    ICONST_1
    IADD
    INVOKEVIRTUAL com/test/ByteCodeTester.setNumber(I)V
   L1
    LINENUMBER 48 L1
    RETURN
   L2
    LOCALVARIABLE this Lcom/test/ByteCodeTester; L0 L2 0
    MAXSTACK = 3
    MAXLOCALS = 1

As you can see, the bytecode still makes the 2 method calls. So the compiler doesn't treat it any differently in this case.



回答6:

number

Except number is a private member of a base class. Then i use the getter/setter to make clear, its not a member of the extending class.

Edit: Oh you ment using it in the main function inside the class? Then ofc e.getNumber() as the other guy said.



回答7:

number if it is used in the same class. And e.getnumber in any subclasses or anywhere outside



回答8:

If the public accessor exists for another purpose, it's preferable to use this accessor, since you'll ensure consistent access to your variable.

However, if your variable does not have a public accessor, it is considered acceptable to access the variable directly. I tend to restrain that to private variables (i.e. no private accessors in the code, but protected accessors instead of protected members if you need access in an implementation of the base class).

So to summarize : I'd always keep the members private and access them through accessors, except if the only accessors needed are private.



回答9:

I generally prefer to still go through the setters/getters, even when accessing the class internally.

I do this because there may be times I want to modify the getters so that it does more than just retrieving a property (e.g., lazy load variable), and I want to have the flexibility of being able to do that without having to worry about modifying other parts of the class.

That said, there are exceptions, though these are for the most part, more personal preference than general best practice. I'll access member variables directly:

  1. When implementing what I consider "low level" functionality (and these are totally subjective, in my case, I consider #equals(), #hashCode(), #toString() and the like "low level"). I don't think there's a very strong technical reason for this, it just "feels" better to me.
  2. If it is way too inconvenient to use the setters/getters (e.g., num ++ vs setNumber(getNumber() + 1) as someone else pointed out).
  3. If my getter does do some additional work, and in my particular case, I do not want that behavior.
  4. ...And there are probably other cases I've missed...


回答10:

say goodbye to multithreading with this.number=.. not to mention eventual need for implementing control of what can be inside this.number. With setNumber() Java concludes this method could be final and can make alot with optimization so you can't sense the difference...



回答11:

Getters/setters are nice in that they often may do slightly more than act as the interface to a private field. The value returned/set may be a part of a more complex calculation that goes on behind the scenes.

The danger however, is that because they are fully fledged method calls, they can literally do anything - start a process, download a file, do an expensive task etc. This is of course silly from the context of a getter/setter but is something to avoid doing. I've also heard of code that performs most of what it's meant to do in getters/setters, having no real methods!!



回答12:

The JVM will optimize away the method call of the setter whenever it is safe to do so (i.e. under almost any case where you would be tempted to just use the field). So for performance, it ought not matter unless you're running on a JVM that doesn't do JIT compilation (e.g. Dalvik). In fact, you can chain method calls many levels deep and the JVM will optimize it away to just a field access when it actually runs it on hardware.

So you generally need not worry about performance costs associated with getters/setters unless they are genuinely doing something extra (which, here, they are not). You can instead make the decision based on other criteria (do you want the flexibility to change the underlying representation? do you want to redefine it in later classes, and if so, is the redefined setter/getter correct, or is the field access correct? etc.).