포스코DX X 비트교육센터 6기 - 자바 객체지향


개발 언어

  • 주개발언어: java, c, c++, c#
  • 세컨언어: JS, python, ruby

  • 절차지향프로그래밍 -> 객체지향프로그래밍 -> 함수형 프로그래밍

객체란?

실세계에 존재하는 것.

  • 학사관리시스템의 학생, 교수님, 수업 정보 등등 정보가 굉장히 많을 것. 이 것의 도메인을 분석하여 의미를 부여하고 분류한 결과로 프로그램을 만들어 적당한 시점에서 객체를 만든다.

  • 필드: 객체의 속성
  • 메소드: 객체의 기능

JVM 메모리 모델

ex. HelloWorld.java가 실행된다.

  • Method Area
    • class loader가 HelloWorld.class 저장.
    • instance 공간과 static 공간으로 나뉨.
    • System class 공간이 자동 호출됨. 객체로 쓰일 때, Heap공간에서 쓰이는 것.
  • Stack
    • camera = 1000 이 들어감. (Goods camera = new Goods();)
  • Heap
    • String은 자동으로 내부에서 new 로, 받아와서 사용 가능. 원래는 String s = new String(“얍”) 이렇게 사용하는데, 내부적으로 처리해줌. Heap에서 배열로 저장.
      • System.out.println(new String(“Hello World”)); = System.out.println(“Hello World”);

image

메소드가 끝났을 때, stack이 pop()으로 정리되게 된다.

접근지정자

  • public : 내부, 외부 , 자식, 다아아아 가능
  • protected : 자식 -> 부모 가능 (자식에서 접근 가능하다) + 같은 패키지 (이건 별 고려해서 protect로 설정하는건아님)
  • private : 다 안돼. 내부에서만 가능 (정보은닉, 캡슐화)

클래스 예시

package chapter03;

public class Goods {
	String name;
	int price;
	int countStock;
	int countSold;
	
	
}

///////////////////

package chapter03;

public class GoodsApp {
	public static void main(String[] args) {
		Goods camera = new Goods();
		camera.name = "Nikon"; // heap 공간에 Nikon이 생성되고 -> heap의 Goods 객체를 가리킴
		camera.price = 400000;
		camera.countStock = 10;
		camera.countSold = 20;
		System.out.println("상품이름 : " + camera.name + ", 가격 : " + camera.price + ", 재고개수 : " + camera.countStock
				+ ", 팔린개수 : " + camera.countSold);
	}
}
  

접근 지정자 예시

  • 파일 구조

image

package mypackage;

public class Goods2 {
	public String name; 	// 모든 접근이 가능하다(접근 제한이 없다)
	protected int price;	// 같은 패키지 + *자식 클래스에서 접근이 가능
	int countStock; 		// 같은 패키지(디폴트)
	private int countSold;  // 클래스 내부에서만 가능
	
	public void m() {
		countSold = 50;
	}
	
	
}

package chapter03;

import mypackage.Goods2;

public class DiscountGoods2 extends Goods2{
	private float discountRate = 0.5f; //double로 생각하기에 f로.. 
	
	public int getDiscountPrice() {
		//protected는 자식에서 접근할 수 있다.
		int discountPrice = (int)(discountRate * price);
		
		return discountPrice;
	}
}


package chapter03;

import mypackage.Goods2;

public class GoodsApp2 {
	public static void main(String[] args) {
		Goods2 camera = new Goods2();
		
		// public : 접근 제한이 없다.
		camera.name = "Nikon"; 
		
		// protected : 같은 패키지에서 접근이 가능하다.
		// 			   더 중요한 접근 제어는 자식에서 접근 가능하다.
		//camera.price = 400000; 다른 패키지 이동 시 오류
		
		// 디폴트 : 같은 패키지에서 접근이 가능하다.
		//camera.countStock = 10; 다른 패키지 이동 시 오류
		
		// private : 같은 클래스에서만 접근이 가능하다.
		//camera.countSold = 20;
		camera.m();

		//System.out.println("상품이름 : " + camera.name + ", 가격 : " + camera.price + ", 재고개수 : " + camera.countStock
		//		+ ", 팔린개수 : " + camera.countSold);
	}
}

private의 getter setter

  • setter

this.name = name

this란? 해당 클래스 내부에 있는 나

package chapter03;

public class Goods3 {
	private String name; //모든 접근이 가능하다(접근 제한이 없다)
	private int price;
	private int countStock;
	private int countSold;
	
	public Goods3() {
	}

	public Goods3(String name, int price, int countStock, int countSold) {
		super();
		this.name = name;
		this.price = price;
		this.countStock = countStock;
		this.countSold = countSold;
	}

	public String getName() {
		return name;
	}

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

	public int getPrice() {
		return price;
	}

	public void setPrice(int price) {
		this.price = price;
	}

	public int getCountStock() {
		return countStock;
	}

	public void setCountStock(int countStock) {
		this.countStock = countStock;
	}

	public int getCountSold() {
		return countSold;
	}

	public void setCountSold(int countSold) {
		this.countSold = countSold;
	}

	@Override
	public String toString() {
		return "Goods2 [name=" + name + ", price=" + price + ", countStock=" + countStock + ", countSold=" + countSold
				+ "]";
	}
	
	
	
}

package chapter03;

public class GoodsApp3 {
	public static void main(String[] args) {
		//Goods3 camera = new Goods3("Nikon", 4000, 10, 20);
		//System.out.println(camera);
		Goods3 camera = new Goods3();
		
		camera.setName("Yewon");
		camera.setPrice(30000);
		camera.setCountStock(20);
		camera.setCountSold(30);
		
		// 정보은닉(데이터보호)
		camera.setPrice(-1);
		
		System.out.println("Goods2 [name=" + camera.getName() + ", price=" + camera.getPrice() + ", countStock=" + camera.getCountStock() + ", countSold=" + camera.getCountSold()
				+ "]");
	}
}

더 깜끔하게~

package chapter03;

public class GoodsApp3 {
	public static void main(String[] args) {
		Goods3 camera = new Goods3("Nikon", 4000, 10, 20);
		
		System.out.println(camera);
		
		
	}
}

정보 보호?

public void setPrice(int price) {
		//정보 보호
		if(price < 0) {
			price = 0;
		}
		this.price = price;
	}

		// 정보은닉(데이터보호)
		camera.setPrice(-1);
		

초기화

  • 지역변수는 명시적 초기화 필요
  • static은 초기화 불필요
int i;
		
		// System.out.println(i); 에러 발생. 지역변수는 초기화가 필요.

변수 별 메모리

  • new를 많이하면 cpu가 느려짐.

image

생성자

public class Goods3 {
	public static int countOfGoods = 0;
	
	private String name; //모든 접근이 가능하다(접근 제한이 없다)
	private int price;
	private int countStock;
	private int countSold;
	
	public Goods3() {
		//내부에서는 클래스 이름 생략 가능
		//Goods.countOfGoods++;
		countOfGoods++;
	}
.
.
.

// countOfGoods 테스트
		Goods3 goods1 = new Goods3();
		Goods3 goods2 = new Goods3();
		Goods3 goods3 = new Goods3();
		
		System.out.println(Goods3.countOfGoods);
		

결과값 : 3 //heap에 3개의 객체가 생성. 초기값으로. 객체가 생성되고 초기화 될 때마다 생성자가 불러오고 method area에 count값이 +1됨.

메소드

  • 메소드 시그너처(signature) : 메소드 인자의 타입, 개수, 순서

  • call : 메소드를 호출하다

    • call by value
    • call by reference

image

결과

a=10, b=20
a=20, b=10

image

결과

a=10, b=20
a=10, b=20

안 바뀌는 이유

image

해결하기 위해서 call by reference를 해주어야함.

package chapter03;

import mypackage.Value;

public class SwapTest03 {
	public static void main(String[] args) {
		Value a = new Value(10);
		Value b = new Value(20);

		System.out.println("a=" + a.val + ", b=" + b.val);
		swap(a, b);

		System.out.println("a=" + a.val + ", b=" + b.val);
	}

	private static void swap(Value m, Value n) {
		int temp = m.val;
		m.val = n.val;
		n.val = temp;
	}

}

package mypackage;

public class Value {
	public int val;

	public Value(int val) {
		this.val = val;
	}
}

image

call by value + call by reference 두 과정을 모두 겪는다.

image

image

static method

package chapter03;

public class StaticMethod {
	int n; //인스턴스 변수
	static int m; //static 변수 = 클래스 변수
	
	void f1() { //인스턴스 메소드
		n =10;
	}
	
	void f2() {
		//같은 클래스의 클래스(static)변수 접근에서는 클래스 이름 생략 가능
		m=20; 
	}
	
	void f3() {
		f2();
	}
	void f4() {
		StaticMethod.s1();
		
		//같은 클래스의 클래스(static)변수 접근에서는 클래스 이름 생략 가능
		s1();
	}
	
	static void s1() {
		//에러: static method 에서는 인스턴스 변수 접근 불가
		// n =10;
	}
	
	static void s2() {
		//에러: static method 에서는 인스턴스 변수 접근 불가
		// f1();
	}
	
	static void s3() {
		StaticMethod.m =10;
		
		//같은 클래스의 클래스(static)변수 접근에서는 클래스 이름 생략 가능
		m=20;
	}
	
	static void s4() {
		StaticMethod.s1();
		
		//같은 클래스의 클래스(static)변수 접근에서는 클래스 이름 생략 가능
		s1();
	}
}

image

image

메소드 사용법 예시

+) 자바 API - Arrays

package chapter03;

import java.util.Arrays;

public class ArrayUtilTest {
	public static void main(String[] args) {
		int[] a = {10,20,30,40};
		// == int[] a = new int[]{10,20,30,40};
		
		double[] d = ArrayUtil.intToDouble(a);
		
		for(int i =0; i<d.length; i++) {
			System.out.println(d[i]);
		}
		
		System.out.println(Arrays.toString(d));
		
		//int[] b = doubleToInt(new double[] {10.0, 20.0, 30.0});
		
		//ArrayUtil.concat(new int[] {1,2,3}, new int[] {4,5,6});
		//System.out.println();
		
	}

	
}

package chapter03;

public class ArrayUtil {

	public static double[] intToDouble(int[] a) {
		double[] d = new double[a.length];
		for(int i = 0; i< a.length; i++) {
			d[i] = a[i];
		}
		
		return d;
	}
	

	public static void concat(int[] is, int[] is2) {
		// TODO Auto-generated method stub
		
	}
}

배열 객체

private static final int COUNT_GOODS = 3;

	public static void main(String[] args) {

		Goods[] goods = new Goods[COUNT_GOODS];

		goods[0] = new Goods(name, price, count); //생성자에 넣어야 null값이 아니라 값 생성
  	}