Item18

상속보다는 컴포지션을 사용하라

상속은 코드를 재사용하는 강력한 수단이지만, 항상 최선은 아니다.

잘못 사용하면 오류를 내기 쉬운 소프트웨어를 만들게 된다.


메서드 호출과 달리 상속은 캡슐화를 깨뜨린다.

  • 상위 클래스가 어떻게 구현되느냐에 따라 하위 클래스의 동작에 이상이 생길 수 있다.
    • 상위 클래스는 릴리스마다 내부 구현이 달라질 수 있으며, 그 여파로 코드 한줄 건드리지 않은 하위 클래스가 오작동할 수 있다.
public class InstrumentedHashSet<E> extends HashSet<E> {
    private int addCount = 0;

    public InstrumentedHashSet(){}

    public InstrumentedHashSet(int initCap, float loadFactor){
        super(initCap, loadFactor);
    }

    @Override
    public boolean add(E e) {
        addCount++;
        return super.add(e);
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        addCount += c.size();
        return super.addAll(c);
    }

    public int getAddCount() {
        return addCount;
    }
}

public class Item18 {
    public static void main(String[] args) {
        InstrumentedHashSet<String> s = new InstrumentedHashSet<>();
        s.addAll(List.of("틱", "탁탁", "펑"));

        System.out.println(s.getAddCount());
    }
}
  • getAddCount()의 결과가 3을 반환하리라 생각하겠지만 6을 반환한다. HashSet의 addAll 메서드가 add 메서드를 사용해 구현된 데 있다.
  • 하위 클래스에서 addAll 메서드를 재정의하지 않으면 문제를 고칠 수 있다.
    • 하지만 이처럼 자신의 다른 부분을 사용하는 '자기사용' 여부는 해당 클래스의 내부 구현방식에 해당하며, 자바 플랫폼 전반적인 정책인지, 그 다음 릴리즈에도 유지될지 알 수 없다.
  • 그렇다면 재정의 대신 새로운 메서드를 추가하면 괜찮을까?
    • 괜찮은 방법이라 생각할수도 있지만, 위험이 전혀 없는 것은 아니다.
    • 다음 릴리스에 상위 클래스에 새 메서드가 추가 됐는데, 운 없게도 하필 추가된 메서드와 시그니처가 같고 반환 타입이 다를 수도 있다. 컴파일 문제가 바로 발생한다.

상속대신 컴포지시션을 이용

기존 클래스를 확장하는 대신, 새로운 클래스를 만들고 private 필드로 기존 클래스의 인스턴스를 참조하게 한다.
컴포지션을 통해 새 클래스의 인스턴스 메서드들은 기존 클래스에 대응하는 메서드를 호출해 그 결과를 반환하게 한다.
새로운 클래스는 기존 클래스의 내부 구현 방식의 영향에서 벗어나며, 심지어 기존 클래스에 새로운 메서드가 추가되더라도 전혀 영향을 받지 않는다.

public class ForwardingSet<E> implements Set<E> {
  private final Set<E> s;

  public ForwardingSet(Set<E> s) {
    this.s = s;
  }

  public void clear() {
    s.clear();
  }

  public boolean contains(Object o) {
    return s.contains(o);
  }

  public boolean isEmpty() {
    return s.isEmpty();
  }

  public int size() {
    return s.size();
  }

  public Iterator<E> iterator() {
    return s.iterator();
  }

  public boolean add(E e) {
    return s.add(e);
  }

  public boolean remove(Object o) {
    return s.remove(o);
  }

  public boolean containsAll(Collection<?> c) {
    return s.containsAll(c);
  }

  public boolean addAll(Collection<? extends E> c) {
    return s.addAll(c);
  }

  public boolean removeAll(Collection<?> c) {
    return s.removeAll(c);
  }

  public boolean retainAll(Collection<?> c) {
    return s.retainAll(c);
  }

  public Object[] toArray() {
    return s.toArray();
  }

  public <T> T[] toArray(T[] a) {
    return s.toArray(a);
  }

  @Override
  public boolean equals(Object o) {
    return s.equals(o);
  }

  @Override
  public int hashCode() {
    return s.hashCode();
  }

  @Override
  public String toString() {
    return s.toString();
  }
}

public class InstrumentedSet<E> extends ForwardingSet<E> {
  private int addCount = 0;

  public InstrumentedSet(Set<E> s) {
    super(s);
  }

  @Override
  public boolean add(E e) {
    addCount++;
    return super.add(e);
  }

  @Override
  public boolean addAll(Collection<? extends E> c) {
    addCount += c.size();
    return super.addAll(c);
  }

  public int getAddCount() {
    return addCount;
  }
}

public class Item18 {
  public static void main(String[] args) {
    InstrumentedHashSet<String> s = new InstrumentedHashSet<>();
    s.addAll(List.of("틱", "탁탁", "펑"));
    System.out.println(s.getAddCount());

    InstrumentedSet<String> s2 = new InstrumentedSet<>(new HashSet<String>());
    s2.addAll(List.of("틱", "탁탁", "펑"));
    System.out.println(s2.getAddCount());
  }
}

결론

  • 상속은 강렬하지만 캡술화를 해친다는 문제가 있다.
  • 상속은 상위 클래스와 하위 클래스가 is-a 관계일 때만 써야 한다.
  • 상위 클래스와 하위 클래스의 패키지가 다를 경우에는 is-a 관계라도 문제가 발생할 수 있다.
  • 상속의 취약점을 피하려면 상속 대신 컴포지션 전달을 사용하자.

참조

블로그 이미지

yhmane

댓글을 달아 주세요

들어가며


 이전 포스팅에서 자바의 클래스에 대하여 알아보았습니다. 이번 포스팅에선 자바의 클래스에서 한단계 더 나아간 인터페이스와 추상클래스에 대하여 알아보도록 하겠습니다.


추상클래스와 인터페이스

 

인터페이스와 추상 클래스는 객체지향적 개념을 개발에 적용하며 설계를 확장하거나 향후 변경하기 쉬운 구조를 지원하는 요소입니다기본적인 속성과 필요한 메서드의 형태(프로토타입만) 기술하고세부적인 내용은 실제 구현 클래스에서 담당합니다.” 


 자바 실무에서 가장 많이 쓰이는 내용이 아닐까 라고 생각합니다. 공통적인 내용을 추상적으로 만들어 설계하는 곳에서 많이 사용됩니다. 실무에서는 보통 선임개발자가 추상클래스/인터페이스를 설계하여 공통된 로직을 적용하고 후임 개발자들이 내용들을 구현하는 용도로 많이 사용됩니다. 아래는 추상클래스와 인터페이스에 대한 내용을 간략히 표로 정리한 것입니다.


 

 추상 클래스

 인터페이스 

 상속 

 단일상속 

 다중상속 

 구현 

 extends 

 implements 

 추상메서드 

 0개 이상 

 모든 메서드 

 객체생성 

 생성불가 

 생성 불가 


  • 추상클래스

 추상클래스는 일반적인 클래스의 추상화 버전입니다. 추상클래스는 개념이나 사물에서 공통되는 특징이나 속성을 추출하여 설계하는 것입니다.

  • 인터페이스
 인터페이스는 추상클래스와 개념상 거의 동일하지만 아래와 같은 차이가 있습니다.

    • 인터페이스는 일반 메서드를 포함할 수 없으며, 모두 추상 메서드로만 구성합니다.
    • 일반 멤퍼 필드는 없고, public, static, final로 선언한 상수만 있습니다. (java8 부터는 생략 가능)
    • 다중 상속이 가능합니다.

추상클래스 예제

abstract class MyAbstractClass {
int num1, num2;
int result;

void calc() {
result = num1 + num2;
}

abstract int getResult();    // 추상메서드는 선언만
}

class MyClass extends MyAbstractClass  {    // extends로 상속 받음
int getResult() {
return result;
}
}

인터페이스 예제

Interface MyInterface {
public static final num = 1000;
public abstract int getResult();
}

class MyClass implements MyInterface {    // implements로 구현 받음
public int getResult() {
return num + 1000;
}
}



참조

- 자바의 정석

- Just 자바

블로그 이미지

yhmane

댓글을 달아 주세요

생성자 대신 정적 팩터리 메서드를 고려하라

클래스의 인스터스를 얻는 전통적인 수단은 public 생성자를 이용하는 것입니다.
하지만, 또 알아두어야 할 기법이 있으니 정적 팩토리 메서드(static factory method)를 이용해서도 제공할 수 있습니다.

public static Boolean valueOf(boolean b) {
    return b ? Boolean.TRUE : Boolean.FALSE;
}

정적 팩토리 메서드가 생성자보다 좋은 장점

  • 이름을 가질 수 있습니다.
class Student() {
    private String name;
    private int studentNum;

    // 어떤 역할인지 명시적 표현.
    public static Student studentWithName(String name) {
         Student student = new Student();
         student.name = name;
         return student;
    }
}

public class Item1 {
    Student student2 = Student.studentWithName("홍길동");
}
  • 호출될 때마다 인스턴스를 새로 생성하지 않아도 됩니다.
class Activity {

    public static final Activity DISCOUNT_THREE_ACTIVITY = new Activity(10000.0, 3);

    private double price;
    private int activityCount;

    public static Activity setPriceWithActivity(int activityCount) {
        // 생성되어 있는 객체를 할당.
        if (activityCount == 3) {
            return DISCOUNT_THREE_ACTIVITY;
        }

        Activity activity = new Activity();
        activity.price = 20000.0;
        activity.activityCount = activityCount;
        return activity;
    }
}

public class Item1 {
    Activity activity = Activity.setPriceWithActivity(3);
}
  • 반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 있습니다.
    생성자는 리턴값이 없지만 정적 팩토리 메소드는 반환값을 유연하게 사용할 수 있습니다.
class Student {
    private String name;
    private int studentNum;
    
    public static MiddleSchool middleSchoolStudnent() {
        return new MiddleSchool();
    }
}
class MiddleSchool extends Student {}
public class Item1 {
    MiddleSchool middleSchool = Student.middleSchoolStudnent();
}
  • 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있습니다.
class Fruit {
    public static Fruit getFruit(String name) {
        if ("Apple".equals(name)) {
           return new Apple();
        } else if ("Banana".equals(name)) {
            return new Banana();
        } else {
            return new Strawberry();
        }
    }
}
class Apple extends Fruit { }
class Banana extends Fruit { }
class Strawberry extends Fruit { }
public class Item1 {
    // 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있습니다.
    Fruit fruit = Fruit.getFruit("Banana");
    System.out.println(fruit.getClass().getName());
}

정적 팩토리 메서드의 단점

  • 상속을 하려면 public, protected의 생성자가 필요합니다.
    정적 팩터리 메서드만 제공하면 하위 클래스를 만들 수 없습니다.
  • API를 따로 제공하지 않기에 프로그래머가 찾기 어렵습니다.



참고

- effective java 3/e [조슈아 블로크]


블로그 이미지

yhmane

댓글을 달아 주세요

들어가며


  자바를 처음 배우게 되면 콘솔 화면을 통해 입력을 하고, 결과값을 출력하게 됩니다. 하지만, 콘솔 화면을 통한 입출력에는 데이터 처리에 대한 한계가 있습니다. 데이터가 휘발성이기 때문에 원하는 결과값을 컴퓨터에 저장하지 못하는데, 이러한 문제를 해결하여 주는 것이 '파일' 입니다. 이러한 문제를 해결 해주기 위해 자바에서는 스트림이라는 것을 통해 파일 입출력을 다룹니다. 이번 포스팅에선 스트림과 파일 관련 클래스에 대하여 알아보도록 하겠습니다.




스트림 (Stream)

 

 Stream은 컴퓨터와 네트워크, 컴퓨터와 주변장치(키보드, 마우스, 모니터, 프린터, 스마트폰 등)간 데이터 통신을 하는 통로입니다. 스트림은 아래와 같은 특성이 있습니다.

  • 스트림은 데이터 송수신의 통로로, Input/Output의 기본이 됨

  • 단방향 통신을 제공 하기 때문에 입력, 출력 두개의 스트림이 필요

  • 스트림은 연속된 데이터 흐름으로 입출력 처리시 다른 작업을 할 수 없는 블로킹 상태

  • 스트림은 문자스트림과 바이트스트림으로 구분


문자스트림

Reader <- BuffredReader, InputStreamReader <- FileReader

Writer <- BufferedWriter, OutputStreamWriter <- FileWriter


바이트스트림

InputStream <- ObjectInputStream, FileInputStream <- DataInputStream, BuffredInputStream

OutputStream <- ObjectOutputSream, FileOutputStream <- DataOutputStream, BufferedOutputStream




파일 개요


 컴퓨터에서 파일은 매우 중요한 입출력 대상입니다. 컴퓨터의 램(RAM) 메모리는 휘발성으로 컴퓨터의 전원이 꺼지면 메모리 상의 모든 데이터는 사라집니다. 하지만, 컴퓨터를 이용하다 보면 게임의 세이브 데이터, 보고서 작성 데이터, 채팅이나 문자 메시지 등 컴퓨터를 종료 하더라도 지워지면 안되는 데이터들이 있습니다. 이처럼 '파일'은 컴퓨터의 메모리 한계를 벗어나 데이터를 저장하고 공유하는 중요한 수단입니다.


 파일 관련 자바 코드를 보기전에, 간단히 용어에 대하여 알아보도록 하겠습니다.


File

- 파일은 컴퓨터 디스크에 텍스스타 바이너리 형태로 저장하기 위해 고안됨

- 텍스트 파일은 프로그램 소스나 메모장에서 작성한 단순 정보를 기록하는 것이 목적

- 바이너리 파일은 이진 형태로 저장 되며 프로그램 실행 파일이나 프로그램에서 저장하는 데이터 파일


Directory

- 대용량 파일을 관리하기 위해 고안됨, '폴더' 라고도 지칭

- 디스크 시스템의 최상위를 루트(ROOT)라 하며, 파일은 루트를 비롯한 하위 디렉토리에 들어 있음


Path

- 경로(Path)는 디스크 시스템에서 파일의 위치를 관리한느 체계

- 파일을 처리 하기 위해서는 파일의 위치 정보가 필요하고, 파일과 디렉토리는 위치를 표현하기 위해 사용됨

- 유닉스 계열은 '/' 윈도우 계열은 '₩'를 구분자로 사용




파일 입출력


 컴퓨터에서 파일은 매우 중요한 입출력 대상입니다. 컴퓨터의 램(RAM) 메모리는 휘발성으로 컴퓨터의 전원이 꺼지면 메모리 상의 모든 데이터는 사라집니다. 하지만, 컴퓨터를 이용하다 보면 게임의 세이브 데이터, 보고서 작성 데이터, 채팅이나 문자 메시지 등 컴퓨터를 종료 하더라도 지워지면 안되는 데이터들이 있습니다. 이처럼 '파일'은 컴퓨터의 메모리 한계를 벗어나 데이터를 저장하고 공유하는 중요한 수단입니다.


  • File 관련 주요 클래스

- File : 경로 정보를 바탕으로 해당 파일 객체를 생성
- FileReader : 파일에서 문자 스트림을 기반으로 한 입력을 처리하는 클래스
- FileWriter : 파일에서 문자 스트림을 기반으로 한 출력을 처리하는 클래스
- FileInputStream : 파일에서 바이트 스트림을 기반으로 한 입력을 처리하는 클래스
FileIOutputStream : 파일에서 바이트 스트림을 기반으로 한 출력을 처리하는 클래스

  • 파일 객체 성성
File file = new File("/Users/hwang-yunho/Documents/temp.txt");

  • 파일 입출력 스트림 생성
FileReader fr = new FileReader(file);
FileReader fr = new FileReader("/Users/hwang-yunho/Documents/temp.txt");
FileInputStream fis = new FileInputStream(file);
FileInputStream fis = new FileInputStream("/Users/hwang-yunho/Documents/temp.txt");

public class JavaEx {
public static void main(String[] args) {

String path = "/Users/hwang-yunho/Desktop/tmp.txt";
File file = new File(path);

try {
FileWriter fw = new FileWriter(file);

for (int i = 'A'; i <= 'z'; i++) {
fw.write(i);
}

fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}


  • Buffered 계열 스트림 연결
BuffredReader br = new BufferedReader(new FileReader("/Users/hwang-yunho/Documents/temp.txt"));
BuffredWriter bw = new BufferedWriter(new FileReader("/Users/hwang-yunho/Documents/temp2.txt"));
public class JavaEx {
public static void main(String[] args) {

String path = "/Users/hwang-yunho/Desktop/tmp.txt";
String newPath = "/Users/hwang-yunho/Desktop/tmp2.txt";
File rFile = new File(path);
File wFile = new File(newPath);

try {
BufferedReader reader = new BufferedReader(new FileReader(rFile));
BufferedWriter writer = new BufferedWriter(new FileWriter(wFile));

String s = "";

while ((s = reader.readLine()) != null) {
writer.write(s);
}

reader.close();
writer.close();
rFile.delete();
} catch (IOException e) {
e.printStackTrace();
}
}
}



정리

 

  • 파일은 컴퓨터에서 가장 기본이 되며 중요한 입출력 대상

  • File 클래스는 바이트 스트림과 문자 스트림을 모두 지원

  • File을 다루기 위해서는 File 객체를 생성하고, 보조 스트림이 필요

  • 서버마다 디렉터리 구분자가 다르니 유의하여 사용 (유닉스 '/' 윈도우 '₩')


출처


- 자바의 정석

- Just 자바

https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html


블로그 이미지

yhmane

댓글을 달아 주세요

들어가며



 이전 포스팅에선 클래스와 객체, 인스턴스의 차이를 간략히 알아보았습니다. 이번 포스팅에선 클래스의 대해 알아볼 것인데 클래스는 프로그래밍의 설계도라고 생각하시면 됩니다


클래스


 

자바에서 클래스(class)란 객체를 정의하는 틀 또는 설계도라고 합니다. 자바에서는 이러한 설계도인 클래스(class)를 가지고 여러 객체를 생성하여 사용하게 됩니다. 클래스는 객체의 상태를 나타내느 필드(field)와 객체의 행위를 나태는 메서드(method)로 구성됩니다.


- 클래스 작성 규칙

  • 숫자로 시작하지 않는다

  • 첫글자는 대문자로 시작한다

  • 일반적으로 카멜 케이스(둘 이상의 단어가 연결 되었을 때, 두번째 단어의 첫글자는 대문자)를 사용한다

class Student
class CityCode
class ItemOrder


  • 필드

객체지향 개념에서 속성에 해당하는 것으로 멤버 변수라고도 합니다. 구조는 다음과 같습니다.


private String name; 한정자 / 자료형 / 변수명


  • 메서드

객체지향 개념에서 행위에 해당하는 것으로, 클래스를 사용하여 실행하는 동작입니다. 구조는 다음과 같습니다.


public int add(int a, int b) { 한정자 / 리턴값 / 함수명(매개변수 ,,,)

return a + b;            리턴키워드 리턴값

}


접근 한정자 - 외부 클래스에서 해당 클래스에 접근하는 범위를 지정합니다. 범위는 아래 표와 같습니다.

 한정자

클래스 내부 

동일 패키지 

하위 클래스 

그외 여역 

 public

 o

 o 

 o 

 o 

 protected

 o 

 o 

 o 

 x 

 default (기본, 생략가능)

 o 

 o 

 x 

 x 

 private

 o 

 x 

 x 

 x 


인스턴스


 클래스를 이용하여 객체를 생성 하게 되는데, 객체를 new 키워드로 할당하게 되면 인스턴스가 생성되어 집니다. 인스턴스가 생성될 때에는 메모리에 올라간 상태입니다.


 인스턴스 생성 방법


Student student = new Student(); 

클래스   참조변수  생성자

  • 생성자

생성자는 클래스나 인스턴스를 생성할 때 호출하는 특수한 목적의 메서드입니다. 일반적으로 변수를 초기화하거나 필요한 다른 개체를 생성하는 작업을 처리합니다. new 키워드를 사용하여 객체를 생성하는 시점에 호출되며, 클래스는 하나 이상의 생성자를 가질 수 있습니다.


생성자 예제

 public class Student {
private String name;
private int age;

public Student() {        // 기본생성자
name = "윤호";
age = 20;
}

public Student(String name, int age) { // 파라미터가 있는 생성자
this.name = name;
this.age = age;
}
}


public class Main {

public static void main(String[] args) {

Student student = new Student();


System.out.println("학생의 이름 : " + student.getName()); // 윤호

System.out.println("학생의 나이 : " + student.getAge());    // 20


Student a = new Student("철수", 30);

System.out.println("학생의 이름 : " + a.getName());          // 철수

System.out.println("학생의 나이 : " + a.getAge());             // 30

}

}


메서드 오버로딩, 오버라이딩


 마지막으로 자바의 객체지향 특성중 다형성과 관련된 기법인 메서드 오버로딩과 오버라이딩에 대하여 알아보겠습니다.

  • 메서드 오버로딩

 메서드 이름을 동일하지만 파라미터가 다른 여러 메서드를 만드는 것을 말합니다.

메서드 오버로딩 특징

- 메서드 이름이 동일합니다.
- 파라미터의 개수 또는 자료형이 다릅니다.
- 파라미터는 같고 리턴 변수의 자료형이 다르면 오버로딩은 성립하지 않습니다.

메서드 오버로딩 예제

public class OverloadingEx {
public int sum(int num1, int num2) {
return num1 + num2;
}

public int sum(int num1, int num2, num3) {
return num1 + num2 + num3;
}

public static void main(String[] args) {
OverloadingEx  ex = new OverloadingEx();
System.out.println(ex.sum(1,2));            // 3
System.out.println(ex.sum(3,4,5));          // 12
}
}
  • 메서드 오버라이딩

 메서드 오버라이딩은 상위 클래스에서 정의한 메서드를 서브 클래스에서 재정의하는 것을 말합니다.

메서드 오버라이딩 특징

- 메서드 이름이 동일합니다.
- 파라미터와 리턴값이 동일합니다.

메서드 오버라이딩 예제

class Person {
public void run() {
System.out.println("뛴다");
}
}


class Student extends Person {
public void run() {
System.out.println("엄청 빨리 뛴다");
}
}

public class Test {
public static void main(String[] args) {
Person person = new Person();
Student student = new Student();

person.run();    // 뛴다
student.runt();    // 엄청 빨리 뛴다
}
}



출처



- 자바의 정석

- just 자바

블로그 이미지

yhmane

댓글을 달아 주세요

들어가며


 이전 포스팅까지는 자바의 기초문법에 대하여 정의하였습니다. 기본적인 문법구조나 변수 선언등에 대해서 알아보았고, 이번 포스팅에선 자바의 가장 두드러지는 특징인 객체지향의 대하여 알아보도록 하겠습니다.


객체지향의 개념


 객체지향이란 컴퓨터 프로그래밍 패러다임중의 한 종류입니다. 기존 명령어를 중심으로 나열하는 프로그래밍기법에서 벗어나, 객체 모델을 바탕으로 프로그램을 구체화하고 개발하는 프로그래밍 기법을 의미합니다. 객체지향의 특징에는 상속, 추상화, 다형, 추상화 이라는 특징이 있습니다.

 위에 언급된 특성은 객체지향의 핵심적인 특징으로 꼭 이해하시고 가야 합니다. 객체지향의 특징을 설명하기 전에 클래스, 객체, 인스턴스를 짚고 넘어가도록 하겠습니다.


  • 클래스

멤버변수와 함수로 구성된 논리적인 설계도


class Student {

private String name;

private int age;

}


  • 객체

클래스에 선언된 모응 그대로 생성된 실체


public class Main {

public static void main(String[] args) {

Student student;

}

}


  • 인스턴스

생성되어진 객체가 메모리에 올려진 것


public class Main {

public static void main(String[] args) {

Student student = new Student();

}

}


객체와 인스턴스는 일반적으로는 통용하여 표현하나, 메모리에 올려진 여부로 객체와 인스턴스를 판단합니다.



객체지향의 특징


 객체지향에는 다음과 같은 특징이 있습니다. 캡슐화, 상속, 다형성, 추상화 모두 중요한 개념입니다. 


  • 캡슐화

 캡슐화는 생성한 객체를 어떤 메서드와 필드로 어떻게 일을 수행할지 외부에 숨기는 특성을 말합니다. 캡슐화 은닉화 라고 하며 보호하고자 하는 데이터의 값을 외부에서 직접 접근하는 것을 방지하기 위해 나온 개념입니다. 접근제어자를 이용하여 값을 은닉하고, public method로 값을 통제합니다.


캡슐화 예제

 class Student {
private String name;
private int age;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

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


public class Main {

public static void main(String[] args) {

Student student = new Student();


student.setName("윤호");

student.setAge(20);


System.out.println("학생의 이름 : " + student.getName());

System.out.println("학생의 나이 : " + student.getAge());

}

}


  • 상속

 클래스는 추상화된 슈퍼클래스와 구체화된 서브 클래스로 구성됩니다. 예를 들면 사람(슈퍼클래스)와 학생(서브클래스)
 지정 예약어 extends를 이용하여 상속을 이용합니다. 하나의 부모클래스는 여러 자식을 가질 수 있지만, 반대는 성립하지 않습니다.
 자식은 부모의 값이나 행위를 상속받아 사용할 수 있습니다. 

상속 예제

class Person {
private String name;
private int age;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

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

public void run() {
System.out.println("달리기를 합니다");
}
}

class Student extends Person() {
public void study() {
System.out.println("공부를 합니다");
}
}


public class Main {

public static void main(String[] args) {

Student student = new Student();


student.setName("윤호");

student.setAge(20);


System.out.println("학생의 이름 : " + student.getName());

System.out.println("학생의 나이 : " + student.getAge());


student.run();

student.study();

}

}


  • 다형성

 클래스의 상속 관계를 이용하여 슈퍼클래스가 같은 서브 클래스의 동일한 요청을 다르게 처리할 수 있는 특징을 말합니다. 예를 들어, 사람이라는 클래스가 있고 아침에 이동하다는 행위를 합니다. 사람을 상속받은 학생클래스는 아침에 학교로 이동하고, 사람을 상속박은 직장인 클래스는 아침에 회사로 이동합니다. 아래 예제를 보도록 하겠습니다.

다형성 예제


class Person {
public void move() {
System.out.println("이동합니다");
}
}

class Student extends Person() {
@Override
public void move() {
System.out.println("학교로 이동합니다");
}
}

class Student extends Worker() {
@Override
public void move() {
System.out.println("일터로 이동합니다");
}
}

public class Main {

public static void main(String[] args) {

Student student = new Student();

Worker worker = new Worker();


student.move();

worker.move();

}

}


  • 추상화

 매우 중요한 개념입니다. 객체의 공통된 특징을 묶어서 추출한다는 개념인데, 다음 포스팅에서 클래스에 대하여 설명하며 추상클래스, 인터페이스와 함께 덧붙이도록 하겠습니다.


정리

 

 이번 포스팅에선 자바의 핵심 개념인 객체지향에 대하여 글을 작성하였습니다. 자바는 프로그램을 구조화하는 특징을 가졌으며 추상화, 상속, 캡슐화, 다형성라는 중요한 특성이 있습니다. 이러한 기능으로 구조적으로 재활용성이 높아져 생산성이나 유지보수 효율성을 높인 프로그래밍 언어입니다!!


출처


- 자바의 정석

- just 자바

블로그 이미지

yhmane

댓글을 달아 주세요

들어가며


 이전에 변수와 자료형에 대하여 학습을 하였습니다. 우리는 값을 메모리에 저장하는데, 이것을 변수라고 합니다. 하지만 반복되거나 집합형의 데이터를 처리하기 위해 많은 변수가 필요할 때가 있습니다. 이런 상황에서 여러 데이터를 순차적으로 관리가 필요해졌고, 이러한 필요성에 의해 '배열' 이라는 자료구조가 나오게 되었습니다.


배열의 개념


 배열은 인덱스(순차적인 번호)와 데이터로 구성된 일종의 자료구조를 말합니다. 데이터는 인덱스를 사용하여 값을 저장하거나 가져옵니다. 모든 언어에서는 배열을 지원하며, 자바 역시 기본적으로 배열을 지원합니다.


사용 분야


집합형의 데이터를 관리할 필요가 있을때 사용


기본 구조


int[] num = new int[4];                            // 크기가 4인 배열 선언

int num[] = new int[4];                            // 위와 같음

int[] num = {10, 20, 30, 40};                      // 배열 선언과 함께 초깃값 할당

int[][] num = {{10, 20}, {30, 40}, {50, 60}};     // 2차원 배열 선언과 함께 초깃값 할당



배열의 특징


 배열은 다음과 같은 특징을 가집니다.


  • 같은 자료형으로만 구성합니다

  • 배열의 인덱스(시작점)은 0부터 입니다.

  • 배열은 선언할 때 크기를 지정해야 하며, 나중에 크기를 변경할 수 없습니다.

  • 초기화되지 않은 인덱스의 값을 조회(참조)할 경우, NPE(Null Pointer Exception)이 발생합니다

 처음에 가장 많이 하는 실수가 num[0]이 아닌 num[1] 부터 접근하는 경우입니다! 또한, NPE은 시스템 운영중 치명적인 문제를 발생할 수 있으므로 항상 주의하여 코드를 작성해야 합니다.

배열 예제

String[] fruit = {"사과", "포도", "오렌지", "바나나"};

for (int i = 0; i < fruit.length; i++) {
System.out.println(fruit[i]);
}

// fruit.length 배열의 크기는 4
// fruit[i]는 0부터 3까지

아래와 같은 순서로 출력됩니다.
// 사과
// 포도
// 오렌지
// 바나나


정리

 

 배열은 자바뿐만 아니라, 모든 언어에서 제공하는 기본적인 자료구조입니다. 집합 또는 반복적인 계산을 처리하기 위해 많이 사용됨으로, 모르신다면 꼭 숙지하고 넘어가시는 게 좋습니다.


출처


- 자바의 정석

- just 자바


블로그 이미지

yhmane

댓글을 달아 주세요

들어가며


 자바라는 프로그래밍 언어를 이용하여 여러가지 연산을 할 수 있습니다. 크게 아래 표와 같은 연산이 있고, 각 연산자의 종류와 용도를 알아보도록 하겠습니다.


 분류 

 연산자 

 설명 

 형변환 연산자 

 (자료형) 

 하나의 항을 형변환

 산술 연산자

 +,-,*,/,%,+=.-=,*=,/=,%= 

 두개의 항이나 왼쪽/오른쪽 항을 연산 

 관계 연산자

 >, <, >=, <=, ==, != 

 대소 관계 

 비트 연산자

 &, ^, |, <<, >> 

 비트 연산 

 논리 연산자

 &&, ||, ! 

 항을 비교하여 참과 거짓의 결과를 연산 


산술 연산자


 우리가 알고 있는 일반적인 연산에 사용됩니다. 사칙연산을 기본으로 하지만 생소한 연산자도 있습니다. 


int num1 = 30;

int num2 = 40;

int num3 = 20;

int num4 = 10;


num1 += 50;    // num1 = num1 + 50 (80)

num2 -= 10;    // num2 = num2 - 10; (40)

num3 *= 20;    // num3 = num3 * 20; (400)

num4 /= 10;    // num4 = num4 / 10; (1)


위와 같은 연산자를 대입연산자 라고 부릅니다.



관계 연산자


 두 피연산자 사이의 대소나 동등의 정도를 측정합니다.


int num = 10;


if (num > 5) {

 num = num + 1;

} else {

 num = num - 1;

}

위의 대소 결과로 num의 값은 6이 됩니다. if 문에 대해서는 다음 포스팅에서 알아보도록 하겠습니다.


논리 연산자


 두 피연산자의 논리적 관계를 정의하며, 조건식에 많이 사용됩니다.


boolean result = (3 < 2) && (4> 1); //  false && true => (false)

boolean result = (3 < 2) || (4> 1); //  false && true => (true)

boolean result = !(3 < 2); //  !false (true)


int num = 3;

int num2 = num == 3 ? 5 : 4; // 삼항연산자이다. num == 3일경우 ? 맞으면 5 틀리면 4


삼항연산자는 자주 사용하므로 사용방법을 알아두는 것이 좋습니다.


(조건) ? 맞을경우 : 틀릴경우


비트 연산자


 비트 연산의 경우 자주 사용하지는 않습니다. 자주 사용하지 않지만, 예전 프로그램 중에 &, | 연산을 이용한 것들이 있기 때문에 &, | 연산에 대해서만 짚고 넘어가도록 하겠습니다.


& 두항의 비트가 모두 1이면 1, 아니면 0으로 연산

| 두 항의 비트가 모두 0이면 0, 아니면 1로 연산

^ 두 항의 비트가 서로 다르면 1, 같으면 0으로 연산


4 & 2   // 100 10 => 000 => 0

6 & 2   // 110 10 => 010 => 2

4 | 2   // 100 10 => 110 => 6


정리


 자바의 기초에 대하여 간단히 포스팅하였습니다. 아마 가장 많이 사용하게 될 연산은 산술과 관계 연산이겠지만 다른 부분도 알고 있어야 합니다.

다음 포스팅에서는 조건, 반복문에 대하여 포스팅 하도록 하겠습니다.


출처


- 자바의 정석

- Just 자바

블로그 이미지

yhmane

댓글을 달아 주세요

들어가며

  • Jdk 설치
  • 환경변수 설정
  • eclipse 설치
자바의 기초문법을 정리하기 전에 이전 3개의 작업을 수행해야 합니다. 어렵지 않은 내용이므로 생략하도록 하겠습니다.
자바의 기초 문법을 복습하고자 글을 정리하며, 혹여나 새로 문법을 익히실 분들에게 도움이 되었으면 합니다 ^^

변수와 자료형


* 변수의 개념


변수란? 변수는 프로그램 안에서 데이터를 저장하는 공간을 의미합니다. 자료형은 변수에 저장할 데이터의 타입(유형)을 의미합니다.


int a;         int는 자료형, a는 변수입니다

int a = 1;   int는 자료형, a는 변수, 1은 초깃값입니다.


간단하게 변수와 자료형에 대하여 알아 보았고, 뒤에서 더욱 풀어서 설명하도록 하겠습니다. 지금은 이런것이 있구나? 라고만 지나가시면 좋을거 같네요.


* 변수 명명 규칙

  • 변수 이름의 길이에는 제한이 없다
  • 문자나 언더바(_), 달러 기호($)로 시작한다
  • 자바의 연산자(+,-,*,/)는 사용할 수 없다
  • 대소문자를 구분한다
  • 변수사이에 빈칸은 올 수 없다
  • 자바의 키워드를 변수 이름으로 사용할 수 없다
int numCount // 카멜 케이스
int num_count // 스네이크 케이스

final int UNDER_ADULT_FEE = 6000

자바의 경우 관례적으로 카멜케이스를 사용합니다. 이례적으로 상수값을 표현할 때는 스네이크 케이스를 이용합니다.


* 기본자료형

자바의 기본 자료형에는 크게 3가지 자료형이 있습니다. 정수형, 실수형, 논리형으로 구분합니다.

* 정수형 

정수형은 처리 단위(크기)와 입출력 범위가 다르다는 점에 주의해야 한다. 특히 서비스를 만들때, db를 많이 이용하게 되는데 pk설정시 intlong을 구별해서 써야 할 경우가 많이 있으니 범위를 잘 알아 두는 것이 좋다. 

 자료형

 크기 

 입출력 범위 

 설명 

 byte 

 1바이트

 -2^7 ~ 2^7 -1

 바이트 통신에 많이 이용

 char

 2바이트

 0 ~ 2^16 -1

 음수 표현 안함, 또는 문자 저장

 short

 2바이트

 -2^15 ~ 2^15 -1

 잘 사용하지 않는다

 int

 4바이트

 -2^31 ~ 2^31 -1

 기본이 되는 자료형

 long

 8바이트

 -2^63 ~ 2^63 -1

 표현범위가 클 경우


* 실수형


정수가 아닌 값을 부동소수점을 사용하여 저장합니다. 정수형보다 정밀하게 숫자를 처리 할 수 있습니다.


 자료형 

 크기

 입출력 범위

 설명

 float

 4바이트

 1.4E^45 ~ 3.402823E^38

 표현 범위가 작고, 숫자에 f를 붙임

 double

 8바이트

 4.9E^324 ~ 3.402823E^308

 기본이 되는 자료형


* 논리형


논리형은 boolean으로 1바이트이고 참/거짓 true/false 값만 가질 수 있다.


정리


 자바의 기초를 배워 보았는데, 변수와 자료형에 대하여 알아 보았습니다. 정리하자면, 변수는 데이터를 담는 '그릇', 자료형은 데이터의 '유형'이라고 생각하면 좋을거 같습니다. 이번 포스팅에선 정말 간단한 부분에 대하여 알아보았는데 다음 포스팅에선 사칙연산에 대하여 알아보도록 하겠습니다.


감사합니다.



출처


- 자바의 정석

- Just Java

블로그 이미지

yhmane

댓글을 달아 주세요




1회독 완료하였습니다.


JPA에 관심 있다면, 또는 프로젝트에 도입을 고려하고 있다면 무조건 구매하세요!!


책이 750페이지가 조금  안 되는데 .. 


하루 30페이지씩 읽는다면 한달이면 완독합니다




Java ORM에 조금이라도 관심이 있으시다면 구매 추천합니다!


- 에이콘 / 김영한님 지음


'Books' 카테고리의 다른 글

이것이 Fedora 리눅스다  (0) 2019.11.23
자바 ORM 표준 JPA 프로그래밍  (0) 2019.07.23
처음 배우는 스프링 부트2  (0) 2019.07.07
Effective JAVA 3/E (이펙티브 자바 3판)  (0) 2019.02.07
블로그 이미지

yhmane

댓글을 달아 주세요