Programing

Java에서 객체와 같은 구조

lottogame 2020. 5. 11. 07:59
반응형

Java에서 객체와 같은 구조


객체와 같은 구조체를 만드는 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();
}

이것은 일반적으로 논의되는 주제입니다. 개체에서 공용 필드를 만드는 단점은 설정된 값을 제어 할 수 없다는 것입니다. 같은 코드를 사용하는 프로그래머가 많은 그룹 프로젝트에서는 부작용을 피하는 것이 중요합니다. 또한 때로는 필드의 객체 사본을 반환하거나 어떻게 든 변환하는 것이 좋습니다. 테스트에서 이러한 메소드를 조롱 할 수 있습니다. 새 클래스를 만들면 가능한 모든 동작이 표시되지 않을 수 있습니다. 방어적인 프로그래밍과 같습니다. 언젠가 getter와 setter가 도움이 될 수 있으며이를 작성 / 사용하는 데 많은 비용이 들지 않습니다. 그래서 그들은 때때로 유용합니다.

실제로 대부분의 필드에는 간단한 게터와 세터가 있습니다. 가능한 해결책은 다음과 같습니다.

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

업데이트 : 속성 지원이 Java 7 또는 그 이후에 추가 될 가능성은 거의 없습니다. Groovy, Scala 등과 같은 다른 JVM 언어는 현재이 기능을 지원합니다. -알렉스 밀러


Java가 "struct"를 지원하는 경우 (동작이 없을 때) 클래스가 기본적으로 "구조"인 경우 공용 인스턴스 변수를 사용하는 것이 적절하다고 말하는 많은 Java 사용자가 Sun Java 코딩 지침에 익숙하지 않은 것 같습니다.

사람들은 게터와 세터가 마치 마치 자바의 중심에있는 것처럼 자바 방식이라고 생각하는 경향이 있습니다. 그렇지 않습니다. 적절한 상황에서 퍼블릭 인스턴스 변수를 사용하여 Sun Java 코딩 지침을 따르면 실제로 불필요한 게터 및 세터로 코드를 복잡하게 만드는 것보다 더 나은 코드를 작성하는 것입니다.

1999 년 Java 코드 규칙은 변경되지 않았습니다.

10.1 인스턴스 및 클래스 변수에 대한 액세스 제공

정당한 이유없이 인스턴스 나 클래스 변수를 공개하지 마십시오. 종종, 메소드 변수의 부작용으로 발생하는 인스턴스 변수를 명시 적으로 설정하거나 가져올 필요가 없습니다.

적절한 퍼블릭 인스턴스 변수의 한 예는 클래스가 기본적으로 데이터 구조이며 동작이없는 경우입니다. 즉, 클래스 대신 구조체를 사용했을 경우 (Java가 구조체를 지원하는 경우), 클래스의 인스턴스 변수를 public으로 설정하는 것이 적절합니다 .

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


상식을 실제로 사용하십시오. 다음과 같은 것이 있다면 :

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

그런 다음 게터와 세터로 감싸는 데 약간의 포인트가 있습니다. 다른 방법으로 x, y 좌표를 전체 픽셀로 저장하지 않습니다. 게터와 세터는 속도를 늦출뿐입니다.

반면에,

public class BankAccount{
    public int balance;
}

나중에 어느 시점에서 잔액이 계산되는 방식을 변경하고 싶을 수도 있습니다. 이것은 실제로 게터와 세터를 사용해야합니다.

규칙을 구부릴 수있는시기를 알 수 있도록 유용한 방법을 적용하는 이유항상 아는 것이 좋습니다.


변경 가능성 문제를 해결하기 위해 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();
    }
}

public필드를 사용하지 마십시오

public클래스의 내부 동작을 실제로 래핑하려는 경우 필드를 사용하지 마십시오 . 가지고 java.io.BufferedReader예를 들어. 다음과 같은 필드가 있습니다.

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

skipLF모든 읽기 방법으로 읽고 씁니다. 별도의 스레드에서 실행되는 외부 클래스 skipLF가 읽기 도중에 상태를 악의적으로 수정 한 경우 어떻게됩니까? BufferedReader확실히 haywire 갈 것입니다.

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));

The class does not have any behavior other than plain getters and setters. It is acceptable to use public fields when the class represents just a data structure, and does not have, and never will have behavior (thin getters and setters is not considered behavior here). It can be written better this way:

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));

Clean!

But remember: Not only your class must be absent of behavior, but it should also have no reason to have behavior in the future as well.


(This is exactly what this answer describes. To quote "Code Conventions for the Java Programming Language: 10. Programming Practices":

One example of appropriate public instance variables is the case where the class is essentially a data structure, with no behavior. In other words, if you would have used a struct instead of a class (if Java supported struct), then it's appropriate to make the class's instance variables public.

So the official documentation also accepts this practice.)


Also, if you're extra sure that members of above Point class should be immutable, then you could add final keyword to enforce it:

public final double x;
public final double y;

By the way, the structure you're giving as an example already exist in the Java base class library as java.awt.Point. It has x and y as public fields, check it out for yourself.

If you know what you're doing, and others in your team know about it, then it is okay to have public fields. But you shouldn't rely on it because they can cause headaches as in bugs related to developers using objects as if they were stack allocated structs (java objects are always sent to methods as references and not as copies).


Re: aku, izb, John Topley...

Watch out for mutability issues...

It may seem sensible to omit getters/setters. It actually may be ok in some cases. The real problem with the proposed pattern shown here is mutability.

The problem is once you pass an object reference out containing non-final, public fields. Anything else with that reference is free to modify those fields. You no longer have any control over the state of that object. (Think what would happen if Strings were mutable.)

It gets bad when that object is an important part of the internal state of another, you've just exposed internal implementation. To prevent this, a copy of the object must be returned instead. This works, but can cause massive GC pressure from tons of single-use copies created.

If you have public fields, consider making the class read-only. Add the fields as parameters to the constructor, and mark the fields final. Otherwise make sure you're not exposing internal state, and if you need to construct new instances for a return value, make sure it won't be called excessively.

See: "Effective Java" by Joshua Bloch -- Item #13: Favor Immutability.

PS: Also keep in mind, all JVMs these days will optimize away the getMethod if possible, resulting in just a single field-read instruction.


I have tried this in a few projects, on the theory that getters and setters clutter up the code with semantically meaningless cruft, and that other languages seem to do just fine with convention-based data-hiding or partitioning of responsibilities (e.g. python).

As others have noted above, there are 2 problems that you run into, and they're not really fixable:

  • Just about any automated tool in the java world relies on the getter/setter convention. Ditto for, as noted by others, jsp tags, spring configuration, eclipse tools, etc. etc... Fighting against what your tools expect to see is a recipe for long sessions trolling through google trying to find that non-standard way of initiating spring beans. Really not worth the trouble.
  • Once you have your elegantly coded application with hundreds of public variables you will likely find at least one situation where they're insufficient- where you absolutely need immutability, or you need to trigger some event when the variable gets set, or you want to throw an exception on a variable change because it sets an object state to something unpleasant. You're then stuck with the unenviable choices between cluttering up your code with some special method everywhere the variable is directly referenced, having some special access form for 3 out of the 1000 variables in your application.

And this is in the best case scenario of working entirely in a self-contained private project. Once you export the whole thing to a publicly accessible library these problems will become even larger.

Java is very verbose, and this is a tempting thing to do. Don't do it.


If the Java way is the OO way, then yes, creating a class with public fields breaks the principles around information hiding which say that an object should manage its own internal state. (So as I'm not just spouting jargon at you, a benefit of information hiding is that the internal workings of a class are hidden behind an interface - say you wanted to change the mechanism by which your struct class saved one of its fields, you'll probably need to go back and change any classes that use the class...)

You also can't take advantage of the support for JavaBean naming compliant classes, which will hurt if you decide to, say, use the class in a JavaServer Page which is written using Expression Language.

The JavaWorld article Why Getter and Setter Methods are Evil article also might be of interest to you in thinking about when not to implement accessor and mutator methods.

If you're writing a small solution and want to minimise the amount of code involved, the Java way may not be the right way - I guess it always depends on you and the problem you're trying to solve.


There is nothing wrong with that type of code, provided that the author knows they are structs (or data shuttles) instead of objects. Lots of Java developers can't tell the difference between a well-formed object (not just a subclass of java.lang.Object, but a true object in a specific domain) and a pineapple. Ergo,they end up writing structs when they need objects and viceversa.


The problem with using public field access is the same problem as using new instead of a factory method - if you change your mind later, all existing callers are broken. So, from an API evolution point of view, it's usually a good idea to bite the bullet and use getters/setters.

One place where I go the other way is when you strongly control access to the class, for example in an inner static class used as an internal data structure. In this case, it might be much clearer to use field access.

By the way, on e-bartek's assertion, it is highly unlikely IMO that property support will be added in Java 7.


I frequently use this pattern when building private inner classes to simplify my code, but I would not recommend exposing such objects in a public API. In general, the more frequently you can make objects in your public API immutable the better, and it is not possible to construct your 'struct-like' object in an immutable fashion.

As an aside, even if I were writing this object as a private inner class I would still provide a constructor to simplify the code to initialize the object. Having to have 3 lines of code to get a usable object when one will do is just messy.


A very-very old question, but let me make another short contribution. Java 8 introduced lambda expressions and method references. Lambda expressions can be simple method references and not declare a "true" body. But you cannot "convert" a field into a method reference. Thus

stream.mapToInt(SomeData1::x)

isn't legal, but

stream.mapToInt(SomeData2::getX)

is.


I don't see the harm if you know that it's always going to be a simple struct and that you're never going to want to attach behaviour to it.


This is a question on Object Oriented Design, not Java the language. It's generally good practice to hide data types within the class and expose only the methods that are part of the class API. If you expose internal data types, you can never change them in the future. If you hide them, your only obligation to the user is the method's return and argument types.


Here I create a program to input Name and Age of 5 different persons and perform a selection sort (age wise). I used an class which act as a structure (like C programming language) and a main class to perform the complete operation. Hereunder I'm furnishing the code...

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+")");
    }
}

The above code is Error Free and Tested... Just copy and paste it into your IDE and ... You know and what??? :)


You can make a simple class with public fields and no methods in Java, but it is still a class and is still handled syntactically and in terms of memory allocation just like a class. There is no way to genuinely reproduce structs in Java.


Sometime I use such class, when I need to return multiple values from a method. Of course, such object is short lived and with very limited visibility, so it should be OK.


As with most things, there's the general rule and then there are specific circumstances. If you are doing a closed, captured application so that you know how a given object is going to be used, then you can exercise more freedom to favor visibility and/or efficiency. If you're developing a class which is going to be used publicly by others beyond your control, then lean towards the getter/setter model. As with all things, just use common sense. It's often ok to do an initial round with publics and then change them to getter/setters later.


Aspect-oriented programming lets you trap assignments or fetches and attach intercepting logic to them, which I propose is the right way to solve the problem. (The issue of whether they should be public or protected or package-protected is orthogonal.)

Thus you start out with unintercepted fields with the right access qualifier. As your program requirements grow you attach logic to perhaps validate, make a copy of the object being returned, etc.

The getter/setter philosophy imposes costs on a large number of simple cases where they are not needed.

Whether aspect-style is cleaner or not is somewhat qualitative. I would find it easy to see just the variables in a class and view the logic separately. In fact, the raison d'etre for Apect-oriented programming is that many concerns are cross-cutting and compartmentalizing them in the class body itself is not ideal (logging being an example -- if you want to log all gets Java wants you to write a whole bunch of getters and keeping them in sync but AspectJ allows you a one-liner).

The issue of IDE is a red-herring. It is not so much the typing as it is the reading and visual pollution that arises from get/sets.

Annotations seem similar to aspect-oriented programming at first sight however they require you to exhaustively enumerate pointcuts by attaching annotations, as opposed to a concise wild-card-like pointcut specification in AspectJ.

I hope awareness of AspectJ prevents people from prematurely settling on dynamic languages.

참고URL : https://stackoverflow.com/questions/36701/struct-like-objects-in-java

반응형