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
공용 변경 가능 필드 대신 공용 변경 불가능 필드 또는 패키지 로컬 변경 가능 필드를 고려하십시오. IMHO가 더 좋을 것입니다.
Peter Lawrey

게터와 세터는 추악하고 장황하지만 Java의 핵심입니다. 간결한 언어입니다. 다른 한편으로는 IDE가 당신을 위해하는 일이기 때문에 절대로 입력해서는 안됩니다. 동적 언어에서는 입력을 적게해야하지만 입력해야합니다 (일반적으로 IDE가 도움이 될 수 있음).
Dan Rosenstark

아이러니하게도 OO는 캡슐화 측면에서 장점이 있지만 CPU와 스토리지 측면에서 지불해야 할 가격이 있습니다. 가비지 콜렉터는 (거의 완전히) 객체 참조를 지워야 할 때 걱정할 필요가 없습니다. C와 같은 구조체를 힙을 사용하여 현재 추세가 완전히 바뀌고 있습니다. 캐싱 유형 솔루션, 프로세스 간 통신, 더 빠른 메모리 집약적 작업, 낮은 GC o / h 및 데이터 세트에 대한 낮은 스토리지 o / h의 이점을 얻을 수 있습니다. 당신이하고있는 일을 알고 있다면, 당신은이 질문을하지 않을 것입니다 ... 그래 다시 생각하십시오!
user924272

@ user924272 : Re "현재 C 형 구조체를 힙으로 사용하여 현재 추세가 완전히 바뀌고 있습니다." Java에서 어떤 작업을 수행합니까 ??? IMHO, 이것은 자바가 시대를 보여주는 영역입니다 ...
ToolmakerSteve

@ToolmakerSteve-원이 보입니다. 나는 유일한 사람이 아니예요. Azul과 같은 회사는 일시 중지없는 가비지 수집에 열광합니다. 자바는 낡았다. 진실. 신음보다는 약점을 발견하고 그것에 대해 무언가를하는 엔지니어? 그들은 존경받을 만하다! +10 from Azul :-)
user924272 2016 년

답변:


62

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

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

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

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


28
즉 C와 같은 # 스타일의 속성을 내가 너무 나쁜 (당신이 무슨 말을하는지와 같은 어떤 소리)
존 Onstott

2
따라서 과부하를 사용하십시오 ... private int _x; 공공 무효 x (int value) {_x = value; } public int x () {return _x; }
Gordon

12
=내 의견으로는 코드를 더 깨끗하게 만드는 것을 선호합니다 .
Svish

6
@ T-Bull : x두 가지 다른 두 가지를 가질 수 있다고해서 좋은 생각은 아닙니다. IMHO, 그것은 인간 독자들에 의한 혼동을 초래할 수있는 잘못된 제안입니다. 기본 원칙 : 독자가 이중 복용을하지 않도록하십시오. 당신이 말하는 것을 분명히하십시오-엔티티마다 다른 이름을 사용하십시오. 차이가 단지 밑줄을 추가하는 것임에도 불구하고. 엔티티를 구별하기 위해 주변 구두점에 의존하지 마십시오.
ToolmakerSteve

2
@ToolmakerSteve : "코딩 스타일과는 반대로) 코딩 교리를 방어 할 때"혼란을 일으킬 수있다 "는 것이 가장 일반적이며 가장 약한 논증입니다. 가장 간단한 것에 혼란스러워 할 사람이 항상 있습니다. 당신은 항상 그가 일주일 정도 깨어 있고 코딩을 한 후 오해의 소지가있는 코딩 스타일을 비난 한 후 실수를했다는 불만을 가진 사람을 찾을 수 있습니다. 나는 그 계산을하지 않습니다. 이 스타일은 유효하고 명백하며 네임 스페이스를 깨끗하게 유지합니다. 또한 여기에는 다른 엔터티가 없으며 / one / 엔터티와 그 주위에 상용구 코드가 있습니다.
T-Bull

290

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


88
+1 실제로 신뢰할 수있는 출처가 있습니다. 다른 모든 대답은 사람들이 사실 인 것처럼 의견을 돌리는 것입니다.
ArtOfWarfare

1
get 및 set 메소드를 사용하여 특성에 액세스하는 산업 표준 방법 인 Java Beans 스펙이 있습니다. 개요는 en.wikipedia.org/wiki/JavaBeans 를 참조하십시오 .
user924272

4
@ user924272 : Java Beans 사양이이 답변과 어떤 관련이 있습니까? "공개 인스턴스 변수"를 사용하는 것이 적절한시기에 대해 설명합니다. 스펙이 인스턴스 변수를 자동으로 속성으로 변환하는 표준 방법 인 경우 C #과 관련이있을 수 있습니다. 하지만 그렇지 않습니까? 그것은 단지 그러한 매핑을 만들기 위해 생성해야 할 상용구 게터와 세터의 이름을 지정합니다.
ToolmakerSteve

@ToolmakerSteve. 이것은 자바 질문입니다. 또한이 질문은 사양이 존재하는 일반적인 문제로 해석되지 않습니다. 구식 관점에서 볼 때 표준 방법이있을 때 필드 돌연변이를 디버깅하는 것이 훨씬 쉽습니다. 세터에서 중단 점을 설정하십시오. 이것은 아마도 현대 디버거로 사용되지 않게되었다, 그러나 나는이 작은 응용 프로그램 좋아하는 동안, 그것은 큰 응용 프로그램 및 대규모 조직에 대한 실제 두통은 ... 클래스가 직접 "펀치"객체에 눈살을 강요 해요
user924272

223

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

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

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

반면에,

public class BankAccount{
    public int balance;
}

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

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


3
이 답변과 함께 필드가 서로 독립적 으로 대담한 한 공개 필드로 클래스를 만들 수 있다고 더 말합니다 . 즉, 한 필드는 다른 필드에 의존하지 않습니다. 이것은 많은 경우 함수에서 여러 개의 리턴 값 또는 극성 코디네이트에 매우 유용 할 수 있습니다. {각도, 길이}는 서로 다르지만 본질적인 방식으로 서로 의존하지 않습니다.
Spacen Jasset 2016 년

@ SpacenJasset : 참고로, 귀하의 예제 (여러 반환 값; 극좌표)가 공개 필드를 사용할지 getter / setter를 사용할 지에 어떤 영향을 미치는지 알 수 없습니다. 반환 값이 여러 개인 경우 호출자가 반환 된 값만 가져와야하기 때문에 역효과를 낳을 수도 있습니다.이 값은 공용 게터 및 개인 세터 (불변)를 선호합니다. 극좌표의 개별 구성 요소에 대한 변경 사항이 다시 (x, y)로 변환되므로 (x, y) 객체에서 극좌표를 반환하는 경우에도 마찬가지입니다. ACCUMULATIVE 수학 오류를 고려하십시오.
ToolmakerSteve

@SpacenJasset : 그러나 나는 당신의 원칙에 동의합니다.
ToolmakerSteve

1
당신은 유효한 지점을 가지고 있지만 픽셀 것은 픽셀 창 (단지 예) 내에 확인하고 이후 나쁜 예입니다 같은 느낌 입니다 뭔가 다른 사람이 할 수도, 게다가,시키는 사람에 픽셀로 설정 (-5, -5)되지 않을 수 있습니다를 좋은 아이디어. :-)
Horsey

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-의견 주셔서 감사합니다-대단히 감사합니다.
Brian

struct "instances"로 final 필드와 함께 final 클래스의 final 인스턴스를 사용하려고 시도했지만 case이러한 인스턴스 필드를 참조 하는 표현식에서을 얻었습니다 Case expressions must be constant expressions. 이 문제를 해결하는 방법은 무엇입니까? 여기서 관용적 개념은 무엇입니까?
n611x007

1
final 필드는 클래스를 처음 사용할 때 초기화되므로 상수가 아닌 객체에 대한 참조입니다. 컴파일러는 객체 참조의 "값"을 알 수 없습니다. 컴파일 할 때 상수를 알아야합니다.
Johan Tidén

1
+1 정말 중요한 답변. 불변의 클래스의 유용성은 내 의견으로는 과소 평가 될 수 없다. 이들의 "fire-and-forget"시맨틱은 특히 멀티 스레드 환경에서 코드에 대한 추론을 더 단순하게 만들어 동기화없이 스레드간에 임의로 공유 할 수 있습니다.
TheOperator

11

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

이 클래스에는 일반 게터 및 세터 이외의 동작이 없습니다. 클래스는 단지 데이터 구조를 나타내며,이없는, 때 공공 필드를 사용하는 것이 허용 하고 행동을 (얇은 getter와 setter가되어주지 않습니다 적이 없습니다 여기에 행동으로 간주). 이 방법으로 더 잘 작성할 수 있습니다.

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)을 사용했다면 클래스의 인스턴스 변수를 public으로 만드는 것이 적절합니다.

따라서 공식 문서 도이 관행을 받아들입니다.)


또한 위 Point클래스의 멤버를 변경할 수 없다고 확신하는 경우 final키워드를 추가 하여 적용 할 수 있습니다 .

public final double x;
public final double y;

8

그런데 예제로 제공하는 구조는 이미 Java 기본 클래스 라이브러리에 있습니다 java.awt.Point. 공개 필드로 x와 y가 있으므로 직접 확인하십시오 .

당신이하고있는 일을 알고 있고 팀의 다른 사람들이 그것에 대해 알고 있다면, 공공 장소를 갖는 것은 괜찮습니다. 그러나 스택 할당 구조체 인 것처럼 객체를 사용하는 개발자와 관련된 버그처럼 두통을 일으킬 수 있기 때문에 의존해서는 안됩니다 (자바 객체는 항상 사본이 아닌 참조로 메서드에 전송 됨).


+1 문제에 대한 적절한 언급-결과가 여전히 C 구조체와 다른 방식. 그러나 Java 객체에 대해 항상 참조로 제기하는 문제는 공개 쓰기 가능 필드 (OP의 질문의 본질-사용할 표현) 대신 세터를 생성하여 개선되지 않습니다. 오히려 NEITHER를 선호하는 주장입니다. IMMUTABILITY에 대한 논쟁입니다. 어느 중 하나로서 수행 할 수 있습니다 public final브라이언의 대답으로, 또는 공용 게터,하지만 공공 세터를함으로써, 필드. 즉, 필드를 사용하는지 접근자를 사용하는지는 중요하지 않습니다.
ToolmakerSteve

8

Re : aku, izb, John Topley ...

가변성 문제를 조심하십시오 ...

게터 / 세터를 생략하는 것이 합리적으로 보일 수 있습니다. 어떤 경우에는 실제로 괜찮을 수도 있습니다. 여기에 제시된 제안 된 패턴의 실제 문제는 변경 가능성입니다.

문제는 최종이 아닌 공개 필드를 포함하는 객체 참조를 전달하는 것입니다. 해당 참조가있는 다른 항목은 해당 필드를 자유롭게 수정할 수 있습니다. 더 이상 해당 객체의 상태를 제어 할 수 없습니다. (문자열이 변경 가능하면 어떻게 될지 생각하십시오.)

해당 객체가 다른 객체의 내부 상태에서 중요한 부분이되면 나빠집니다. 내부 구현을 방금 노출했습니다. 이를 방지하려면 대신 오브젝트 사본을 리턴해야합니다. 이 방법은 효과가 있지만 수많은 일회용 복사본으로 인해 엄청난 GC 압력이 발생할 수 있습니다.

공개 필드가있는 경우 클래스를 읽기 전용으로 설정하십시오. 필드를 생성자에 매개 변수로 추가하고 필드를 final로 표시하십시오. 그렇지 않으면 내부 상태가 노출되지 않도록하고 반환 값에 대해 새 인스턴스를 생성해야하는 경우 지나치게 호출되지 않도록하십시오.

Joshua Bloch의 " 유효한 Java "-항목 # 13 : 선호 불변성 참조.

추신 : 요즘 모든 JVM은 가능한 경우 getMethod를 최적화하여 단일 필드 읽기 명령을 생성합니다.


12
게터 / 세터는이 문제를 어떻게 해결합니까? 여전히 참조가 있고 작업과 동기화되지 않았습니다. 게터 / 세터는 그 자체로 보호 기능을 제공하지 않습니다.
he_the_great

1
Getter와 Setter는 필요한 경우 동기화를 제공 할 수 있습니다. 또한 getter와 setter가 지정된 것보다 훨씬 많은 작업을 수행 할 것으로 기대합니다. 이것에 관계없이 동기화 문제는 여전히 재조정됩니다.
user924272

7

나는 게터와 세터가 의미 론적으로 의미없는 균열로 코드를 어지럽히고 다른 언어는 규칙 기반의 데이터 숨기기 또는 책임 분할 (예 : 파이썬)로 잘 작동한다고 생각하는 몇 가지 프로젝트에서 이것을 시도했습니다.

다른 사람들이 위에서 언급했듯이 두 가지 문제가 있으며 실제로 해결할 수는 없습니다.

  • 자바 세계의 자동화 된 도구는 getter / setter 규칙에 의존합니다. 다른 사람들이 지적한 것처럼 jsp 태그, 스프링 구성, 이클립스 도구 등을위한 Ditto ... 도구가 기대하는 것과 싸우는 것은 Google을 통해 긴 세션을 스크롤하여 비표준 방식을 시작하는 방법을 찾는 방법입니다 봄 콩. 정말 문제가되지 않습니다.
  • 수백 개의 공용 변수로 우아하게 코딩 된 응용 프로그램을 만든 후에는 불변성이 절대적으로 필요하거나 변수가 설정되거나 던질 때 이벤트를 트리거 해야하는 상황이 적어도 하나 이상 발견 될 수 있습니다 객체 상태를 불쾌한 것으로 설정하기 때문에 변수 변경에 대한 예외. 그런 다음 변수가 직접 참조되는 모든 곳에서 특정 방법을 사용하여 코드를 어지럽히는 응용 프로그램과 응용 프로그램의 1000 개 변수 중 3 개에 대한 특수 액세스 양식이 있어야합니다.

그리고 이것은 독립적 인 개인 프로젝트에서 전적으로 작업하는 최상의 시나리오입니다. 모든 것을 공개적으로 접근 가능한 라이브러리로 내 보내면 이러한 문제는 더욱 커질 것입니다.

자바는 매우 장황하며, 이것은 유혹적인 일입니다. 하지마


공공 장소로가는 문제에 대한 훌륭한 토론. Java의 확실한 단점은 C #에서 Java로 다시 전환해야 할 때 짜증납니다 (Java의 불편 함을 통해 배웠습니다).
ToolmakerSteve

4

Java 방식이 OO 방식이라면, 예, 공개 필드로 클래스를 만들면 객체가 자체 내부 상태를 관리해야한다는 정보 숨기기에 대한 원칙이 깨집니다. (따라서 전문 용어를 내뱉는 것이 아니라 정보 숨기기의 장점은 클래스의 내부 작업이 인터페이스 뒤에 숨겨져 있다는 것입니다. 아마도 돌아가서 클래스를 사용하는 클래스를 변경해야 할 것입니다 ...)

또한 JavaBean 네이밍 호환 클래스에 대한 지원을 이용할 수 없으므로 Expression Language를 사용하여 작성된 JavaServer Page에서 클래스를 사용하기로 결정하면 손상 될 수 있습니다.

JavaWorld 기사 Getter 및 Setter 메소드가 악의적 인 기사 인 경우 접근 자 및 변경자 메소드를 구현하지 않을시기에 대해 생각하는 데 관심이있을 수 있습니다.

작은 솔루션을 작성 중이고 관련된 코드의 양을 최소화하려는 경우 Java 방식이 옳지 않을 수 있습니다. 항상 귀하와 해결하려는 문제에 달려 있다고 생각합니다.


1
"Getter 및 Setter 메서드가 악한 이유"기사에 대한 링크는 +1입니다. 그러나 공개 필드와 공개 getter / setter가 모두 Java 방식이 아니라는 점을 지적하면 대답이 명확했을 것입니다.이 기사에서 설명한 것처럼 가능하면 수행하지 마십시오. 대신, 인스턴스의 내부 표현을 미러링하는 대신 클라이언트에게 필요한 작업에 고유 한 방법을 제공하십시오. 그러나 이것은 실제로 질문되고있는 질문 (단순한 "struct"경우에 사용)에 대해서는 다루지 않으며, developer.g, izb 및 Brian이 더 잘 응답합니다.
ToolmakerSteve

3

저자 객체 대신 구조체 (또는 데이터 셔틀) 임을 알고 있다면 해당 유형의 코드에는 아무런 문제가 없습니다 . 많은 Java 개발자는 올바르게 구성된 객체 (java.lang.Object의 서브 클래스가 아니라 특정 도메인 의 실제 객체)와 파인애플 의 차이점을 알 수 없습니다 . Ergo, 객체와 객체가 필요할 때 구조체를 작성합니다.


파인애플 날 웃게 만들어 :)
기 illa

그러나이 답변은 그 차이점에 대해 아무 것도 말하지 않습니다. 비 숙련 개발자를 ing 아도 개발자가 언제 구조체를 만들고 언제 수업을하는지 알 수 없습니다.
ToolmakerSteve

저자가 차이점을 알고 있기 때문에 차이점에 대해 아무 말도하지 않습니다 (구조와 같은 실체가 무엇인지 알고 있습니다). 저자는 OO 언어로 구조체를 사용하는 것이 적합한 지 묻고 있습니다 (문제 도메인에 따라 다름). 논의.
luis.espinal

또한, 차이를 모르는 유능한 개발자의 유일한 유형은 여전히 ​​학교에있는 것입니다. 이것은 연결된 목록과 해시 테이블의 차이점을 아는 것과 같이 매우 근본적입니다. 어떤 사람이 진정한 대상이 무엇인지 모른 채 4 년제 소프트웨어 학위를 취득한 경우,이 사람은이 직업을 위해 삭감되지 않았거나 학교로 돌아가서 환불을 요구해야합니다. 나는 진지하다.
luis.espinal

그러나 귀하의 불만을 충족시키기 위해 답변을 제공합니다 (원래 질문과 관련이 거의 없으며 자체 스레드가 필요합니다). 객체에는 동작이 있고 상태가 캡슐화됩니다. Structs는 그렇지 않습니다. 객체는 상태 머신입니다. Structs는 단지 데이터를 집계하기위한 것입니다. 사람들이 더 정교한 답변을 원한다면, 마음의 내용을 정교하게 다룰 수있는 새로운 질문을 자유롭게 만들 수 있습니다.
luis.espinal

2

공개 필드 액세스 사용과 관련된 문제는 팩토리 방법 대신 새 필드를 사용하는 것과 같은 문제입니다. 나중에 마음이 바뀌면 기존의 모든 발신자가 끊어집니다. 따라서 API 진화 관점에서 볼 때 총알을 물고 게터 / 세터를 사용하는 것이 좋습니다.

내가 다른 방향으로가는 곳은 내부 데이터 구조로 사용되는 내부 정적 클래스와 같이 클래스에 대한 액세스를 강력하게 제어하는 ​​것입니다. 이 경우 필드 액세스를 사용하는 것이 훨씬 더 명확 할 수 있습니다.

그런데 e-bartek의 주장에 따르면 Java 7에서 속성 지원이 추가 될 가능성은 거의 없습니다.


1
이것은 사실이지만 Java를 사용하는 경우 한 번의 클릭으로 전체 코드베이스를 리팩터링 할 수 있기 때문에 걱정할 필요가 없습니다 (Eclipse, Netbeans, VIM 및 Emacs도 가능). Groovy와 같이 역동적 인 친구 중 한 명을 선택했다면 간단한 캡슐화로 몇 시간 또는 며칠 동안 고칠 수 있습니다. 운 좋게도 더 많은 코드를 수정해야 할 테스트 사례가 있습니다.
Dan Rosenstark

2
물론 모든 사용자가 코드베이스에 있지만 물론 사실이 아니라고 가정합니다. 기술적이지 않은 이유로 여러 가지 이유로 자신의 코드 기반에있을 수있는 코드를 변경하는 것도 불가능합니다.
Alex Miller

2

코드를 단순화하기 위해 개인 내부 클래스를 만들 때이 패턴을 자주 사용하지만 이러한 객체를 공개 API에 노출하지 않는 것이 좋습니다. 일반적으로 퍼블릭 API의 객체를 변경할 수없는 빈도가 높을수록 'struct-like'객체를 변경할 수 없습니다.

옆으로,이 객체를 개인 내부 클래스로 작성하더라도 객체를 초기화하는 코드를 단순화하는 생성자를 계속 제공합니다. 사용할 수있는 객체를 얻기 위해 3 줄의 코드가 있어야하는 것은 지저분합니다.


2

아주 오래된 질문이지만 또 다른 짧은 기여를하겠습니다. Java 8에는 람다 식과 메서드 참조가 도입되었습니다. Lambda 표현식은 간단한 메소드 참조 일 수 있으며 "참"본문을 선언하지 않습니다. 그러나 필드를 메소드 참조로 "변환"할 수 없습니다. 그러므로

stream.mapToInt(SomeData1::x)

합법적이지는 않지만

stream.mapToInt(SomeData2::getX)

입니다.


이 경우 data -> data.x여전히 합리적입니다
James Kraus

1

그것이 항상 간단한 구조체가 될 것이고 행동을 결코 붙이고 싶지 않을 것이라는 것을 알고 있다면 해를 보지 않습니다.


1

이것은 Java 언어가 아닌 객체 지향 디자인에 관한 질문입니다. 일반적으로 클래스 내에서 데이터 유형을 숨기고 클래스 API의 일부인 메소드 만 노출하는 것이 좋습니다. 내부 데이터 형식을 공개하면 나중에 변경할 수 없습니다. 그것들을 숨기면 사용자에게 유일한 의무는 메소드의 반환 및 인수 유형입니다.


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에서 구조체를 실제로 재현하는 방법은 없습니다.


0

때로는 메서드에서 여러 값을 반환해야 할 때 이러한 클래스를 사용합니다. 물론 그러한 개체는 수명이 짧고 가시성이 매우 제한적이므로 괜찮습니다.


0

대부분의 경우와 마찬가지로 일반적인 규칙이 있으며 특정 상황이 있습니다. 주어진 객체가 어떻게 사용 될지 알 수 있도록 닫힌 캡처 응용 프로그램을 수행하는 경우 가시성과 효율성을 높이기 위해 더 많은 자유를 행사할 수 있습니다. 당신이 통제 할 수없는 다른 사람들이 공개적으로 사용할 클래스를 개발하고 있다면, getter / setter 모델에 의존하십시오. 모든 것과 마찬가지로 상식 만 사용하십시오. 대중과의 첫 라운드를 한 다음 나중에 게터 / 세터로 변경하는 것이 좋습니다.


0

Aspect 지향 프로그래밍을 사용하면 할당이나 가져 오기를 포착하고 가로 채기 논리를 첨부 할 수 있습니다. 문제를 해결하는 올바른 방법입니다. (공개 또는 보호되어야하는지 또는 패키지로 보호되어야하는지의 문제는 직교입니다.)

따라서 올바른 액세스 규정자가있는 인터셉트되지 않은 필드부터 시작하십시오. 프로그램 요구 사항이 증가함에 따라 논리를 연결하여 유효성을 검사하고 반환되는 객체의 복사본 등을 만듭니다.

게터 / 세터 철학은 필요하지 않은 수많은 간단한 경우에 비용을 부과합니다.

애스펙트 스타일이 더 깨끗한 지 아닌지는 다소 질적입니다. 클래스의 변수 만보 고 논리를 개별적으로 보는 것이 쉽다는 것을 알았습니다. 사실, Apect 지향 프로그래밍의 요점은 많은 관심사가 크로스 커팅되고 클래스 본문 자체에서 구획화하는 것이 이상적이지 않다는 것입니다 (로그 기록의 예-모든 로그를 원하면 Java가 원합니다) 전체 게터를 작성하고 동기화를 유지하지만 AspectJ는 하나의 라이너를 허용합니다).

IDE의 문제는 청각입니다. 입력 / 설정에서 발생하는 읽기 및 시각적 오염만큼 타이핑이 아닙니다.

어노테이션은 언뜻보기에는 어 스펙트 지향 프로그래밍과 비슷해 보이지만 AspectJ의 간결한 와일드 카드와 같은 포인트 컷 스펙과 달리 어노테이션을 첨부하여 포인트 컷을 철저하게 열거해야합니다.

AspectJ에 대한 인식으로 사람들이 동적 언어에 조기에 정착하지 못하게되기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.