생각기록

2023-03-02 java 클래스 / 객체지향 프로그래밍 / getter, setter / static 본문

SeSAC 풀스택/JAVA &Spring boot

2023-03-02 java 클래스 / 객체지향 프로그래밍 / getter, setter / static

끼록관 2023. 3. 2. 18:31

객체지향 프로그래밍

• 필요한 데이터와 코드를 묶어 하나의 객체로 만들고 이 객체들 간에 상호작 용을 하도록 프로그램을 만드는 방식

 

먼저 객체를 설계

기능을 메소드로 정의하고

그 객체들을 조합해서 프로그래밍 하는 방식

 

예시 ) 자판기와 사람

사람이라는 개체는 돈을 넣고 음료수 거스름돈을 받고 그런 행동을 메소드로 지정

자판기 거스름돈을 주고 음료수를 주는 메소드등 이런식으로 객체를 조합해서

그런것들을 모아서 객체지향프로그래밍을 한다

 

장점

• 코드 재사용에 용이

• 유지보수 용이

 

 단점

• 처리속도가 느림 => 여러 객체를 왓다갓다 접근해서 절차지향보다 조금 느리다. but 자바는 절차지향 대표 언어

• 설계가 복잡함

 

클래스는 객체를 설계하는 틀

 

클래스

클래스의 구조

• 필드(변수) : 클래스 내에서 값을 저장하는 변수

• 메소드 : 클래스 내에 선언된 함수

• 생성자 : 객체가 생성될 때 자동으로 호출되는 메소드

 

메소드 기본 구조

메소드 형태

생성자

• 생성자의 이름은 클래스 이름과 같아야 함.

• 생성자는 리턴 타입을 적지 않음.

 

 

클래스의 사용 (객체 만들기)

 new 키워드 이용

• test는 객체.

• test는 ClassName 클래스의 인스턴스다

 

 

 


사람이라는 새 패키지 클래스를 생성해서 써보기

name: 원하는 클래스명

메인메소드 public static void main(String[] args)

메인메소드가 여기서는 필요없어서 체크 해제 

 

1. 필요한 값을 필드(변수) 설정 이름과 나이가 필요

public String name;

...

 

2. 생성자 생성

* 생성자는 객체가 생성될때 자동 호출 된다.

public Person ( String name, ... ) {

생성자에서 받은 값을 위의 필드값을 의미하도록 지정

 this.name = name;  // public String name;

...

}

 

3. 메소드 정의

메소드는 클래스 내에 선언된 함수, 즉 행동

public void myname() {

// 해당 함수 호출 하면, 입력받은 name 을 콘솔에 찍는다.

 System.out.println("my name is " + name ) ;

}

package java_first_project;

public class person {
	
    // 필드(변수) 클래스 내에서 값을 저장하는 변수
	public String name;
	public int age;
	
	// 생성자 > 객체가 생성될때 자동 호출 됨
	// 클래스 명과 같습니다. 리턴 타입을 적지 않는다.
	public person( String name, int age) {
    	// 객체가 생성될때마다 welcome이 띄워짐
		System.out.println("welcome");
        
		//public String name 를 의미 > 인자를 myname 이런식으로 변경해도 된다(this 없이!)
		this.name = name;
		this.age = age;
	}
	
	// 메소드 정의
    // 접근 제어자 리턴타입 함수 이름
	public void myname() {
		System.out.println("my name is " + name );
	}
}

메인에서 객체 생성시 값을 보내고 있다.

 

4. 만들어진 클래스를 사용한다

main 패키지로 가서

new 키워드 사용

 

객체를 만들면서, 값을 보내기

person person1 = new person("수남쓰", ... );

 

이 객체에 해당하는 함수 실행

person1.myname();

 => my name is 수남쓰

package java_first_project;

import java.util.Scanner;


public class Main {
	
	
	public static void main(String[] args) {
		
		person person1 = new person("수남쓰", 10);
		person person2 = new person("박하쓰", 3);
		person person3 = new person("밤이쓰", 1);
		person1.myname();
		person2.myname();
		person3.myname();

	}
}

실습

 

package java_first_project;

// Rectangle 클래스
public class Rectangle {
	
    // 필드(변수)  클래스 내에서 값을 저장하는 변수
	public int width;
	public int height;
	
	// 생성자 > 객체가 생성될 때 자동으로 호출되는 메소드
    // 생성자는 클래스와 이름이 같습니다.
	public Rectangle(int width, int height) {
    	// 필드를 의미
		this.width = width;
		this.height = height;
	}
	
	// 메소드 > 클래스 내에 선언된 함수
	public int area() {
		System.out.println(width * height);
	}
}
package java_first_project;

import java.util.Scanner;


public class Main {
	
	
	public static void main(String[] args) {
		
		Scanner scanner = new Scanner(System.in);

		System.out.println("사각형의 가로와 세로 길이를 띄어쓰기를 기준으로 입력하시오");
		
		int wnum = scanner.nextInt();
		int hnum = scanner.nextInt();
		// 객체를 만들때 값을 보냅니다.
		Rectangle Rectangle1 = new Rectangle(wnum, hnum);
		
		Rectangle1.area();

	}
}

선생님 코드 나랑 다른점

package java_first_project;


public class Rectangle {
		
	public int width;
	public int height;
	
	// 생성자
	public Rectangle(int width, int height) {
		// 필드를 의미
		this.width = width;
		this.height = height;
	}
	
	// 메소드 정의
	public int area() {
		return width * height;
	}
}

내 코드는 메소드에 void 로 타입지정을 / 선생님은 리턴을 메인에 반환하기 위해 int로 하셨다.

package java_first_project;

import java.util.Scanner;

public class Main {
	
	
	public static void main(String[] args) {
		
		Scanner scanner = new Scanner(System.in);

		System.out.println("사각형의 가로와 세로 길이를 띄어쓰기를 기준으로 입력하시오");
		
		// 띄워쓰기를 기준으로 입력하니까 nextInt
		int wnum = scanner.nextInt();
		int hnum = scanner.nextInt();
		// 객체를 만들때 값을 보냅니다.
		Rectangle Rectangle1 = new Rectangle(wnum, hnum);
		
		System.out.println( Rectangle1.area());

	}
}

main에서 콘솔찍고있음

 


접근 제어자

편지 봉투 같이 생긴것을 패키지라고 합니다.

관련있는 파일을 저장하는 곳

 

mvc 패턴 사용했던것처럼 스프링에서도 사용하게 된다

그런것을 패키지로 만들어서 파일을 관리하게 된다.

 

• 접근 제어자의 목적

• 클래스나 일부 멤버(필드, 메소드)를 외부에서의 접근 제한을 걸어두는 것

 

 

접근 제어자의 종류

• public

• 패키지에 관계 없이 모든 클래스에서 접근 가능

 

• protected

• 같은 패키지 내의 모든 클래스에서 접근 가능 (다른 패키지에서 접근 불가)

• 단, 다른 패키지에 있더라도 상속 받은 서브클래스에서는 접근 가능

 

• default

• 같은 패키지 내의 모든 클래스에서 접근 가능 (다른 패키지에서 접근 불가)

• private • 같은 클래스에서만 접근 가능

 

 

 

test 패키지 안에 test 클래스 생성

 

여기 다 놓쳣다.... 피눈물.. 

 


getter와 setter

• 클래스에서 필드(변수)는 private로 지정하 는 것이 일반적이다.

• 따라서 간접적으로 필드에 접근할 수 있도록 public 메소드를 제공한다.

• 이것을 getter와 setter 라고 한다.

• getter: 필드 값을 가져올 때

• setter: 필드 값을 설정할 때

 

 

자동으로 생성하는 getter, setter 기능도 있다.

 

 

package java_first_project;

public class person {
	
	public String name;
	public int age;
	
	
	// getter * setter
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	public String getAge() {
		return name;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	
	// 메소드 정의
	public void myname() {
		System.out.println("my name is " + name );
	}
}

ㅠㅠ

package java_first_project;

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

		person person1 = new person();
		// 값을 설정하고
		person1.setName("수남아");
		// 가져와진다..?
		System.out.print(person1.getName());
	}
}

 

 


실습

package java_first_project;


public class Rectangle {
		
	private int width;
	private int height;
	
	// 생성자
	public Rectangle(int width) {
		// 필드를 의미
		this.width = width;
	}
	
	// getter * setter
	public int getWidth() {
		return width;
	}

	public void setWidth(int width) {
		this.width = width;
	}

	public int getHeight() {
		return height;
	}

	public void setHeight(int height) {
		this.height = height;
	}
	
	
	// 메소드 정의
	public int area() {
		return width * height;
	}
}
package java_first_project;

import java.util.Scanner;
import java.util.ArrayList;

public class Main {
	
	
	public static void main(String[] args) {
		
		Scanner scanner = new Scanner(System.in);
		
		// Rectangle 객체를 담을 예정 타입이 Rectangle인 ArrayList 생성
		ArrayList<Rectangle> rect = new ArrayList();
				
		while(true) {
			System.out.println("사각형의 가로와 세로 길이를 띄어쓰기를 기준으로 입력하시오");
			// 띄워쓰기를 기준으로 입력하니까 nextInt
			int wnum = scanner.nextInt();
			int hnum = scanner.nextInt();
			
			// String은 객체여서 즉, 참조형이라 equals()로 비교해야 한다.
			// 하지만 지금 문자열이 아니니 == 을 써야한다.
			if(wnum == 0 && hnum == 0) {
				break;
			}
			// else 둘다 0이 아닐때 추가 되도록
			// 새로운 rectangle1에 width 값을 보내준다
			Rectangle rectangle1 = new Rectangle(wnum);
			// 세로 길이는 setHeight setter로 추후 설정이 가능하다.
			rectangle1.setHeight(hnum);
			// 값들이 다 설정되어 해당 객체를 배열 rect 뒤에 추가합니다.
			rect.add(rectangle1);
		}
		
		// 배열 출력을 하기위해 for문을 씁니다.
		// ArrayList는 .length를 x > .size();
		for (int i = 0; i < rect.size(); i++) {
			System.out.println("가로 길이는 : " + rect.get(i).getWidth());
			System.out.println("세로 길이는 : " +rect.get(i).getHeight());
			System.out.println("넓이는 : " + rect.get(i).area());
			System.out.println("=================");
		}


	}
}

주의할점은

숫자형은 기본타입이라 == 으로 하면 된다!

String 은 참조 타입이라서 .equals 를 써야 했었다.

 

선생님 코드

package java_first_project;

import java.util.Scanner;
import java.util.ArrayList;

public class Main {
	
	
	public static void main(String[] args) {
		
		Scanner scanner = new Scanner(System.in);
		
		// Rectangle 객체를 담을 예정 타입이 Rectangle인 ArrayList 생성
		ArrayList<Rectangle> rect = new ArrayList();
				
		while(true) {
			System.out.println("사각형의 가로와 세로 길이를 띄어쓰기를 기준으로 입력하시오");
			// 띄워쓰기를 기준으로 입력하니까 nextInt
			int wnum = scanner.nextInt();
			int hnum = scanner.nextInt();
			
			// String은 객체여서 즉, 참조형이라 equals()로 비교해야 한다.
			// 하지만 지금 문자열이 아니니 == 을 써야한다.
			if(wnum == 0 && hnum == 0) {
				break;
			}
			// else 둘다 0이 아닐때 추가 되도록
			// 새로운 rectangle1에 width 값을 보내준다
			Rectangle rectangle1 = new Rectangle(wnum);
			// 세로 길이는 setHeight setter로 추후 설정이 가능하다.
			rectangle1.setHeight(hnum);
			// 값들이 다 설정되어 해당 객체를 배열 rect 뒤에 추가합니다.
			rect.add(rectangle1);
		}
		
		// 배열 출력을 하기위해 for문을 씁니다.
		// ArrayList는 .length를 x > .size();
		for (Rectangle rectangle : rect) {
			System.out.println("가로 길이는 : " + rectangle.getWidth());
			System.out.println("세로 길이는 : " + rectangle.getHeight());
			System.out.println("넓이는 : " + rectangle.area());
			System.out.println("=================");
		}
	}
}

밑에서 그냥 for-each에 Rectangle 객체를 넣어주면 된다.

rectangle은 임의로 네이밍이 가능하다.

 

 


static

정적인

변수나 메소드에 붙일 수 있는데

 

static 멤버(변수, 메소드)

객체마다 생성되는 것이 아니고, 클래스당 하나만 생성됨

• 클래스가 생성되는 순간에 메모리를 할당 받음.

• 즉, 객체를 생성하지 않아도 static 멤버에 접근 가능

• 동일한 클래스의 모든 인스턴스에 공유됨. (같은 메모리 공간 공유)

• non-static의 경우 객체가 생성될 때마다 멤버 공간을 새로 만듦. → 메모리 공간이 공유되지 않음.

package java_first_project;

public class Main {
	
	
	public static void main(String[] args) {
		
		
		Number number1 = new Number();
		// number2 은 static이 아님!
		Number number2 = new Number();

	}
}
package java_first_project;

public class Main {
	
	
	public static void main(String[] args) {
		
		
		Number number1 = new Number();
		// number2 은 static이 아님!
		Number number2 = new Number();
		
		// static 맴버는 클래스당 하나만 생성 (객체당 생성 x)
		// number1 객체가 값을 바꿔서 num1이란 필드도 바뀌었다.
		// 원래같으면 number2의 num1은 static으로 값이 1로 설정되어서 나온다.
		number1.num1 = 1;
		number1.num2 = 1;
		
//		number1 의 num1, num2는 1, 1 로 나옴
		System.out.println(number2.num1);
		System.out.println(number2.num2);
	}
}

static 멤버는

같은 메모리 공간 공유

필드를 모든 객체가 공유하고 있다.

 

 

 

Static의 활용

• 보통 static 변수는 공유의 목적으로 많이 사용됨.

• static 메소드는 유틸리티성 메소드를 작성할 때 많이 사용됨

.ex) 오늘의 날짜 구하기, 숫자에 콤마 추가하기 등등..

ex) java.lang 패키지의 Math 클래스

 

Static의 제약

• static 메소드에서 non-static 멤버에 접근할 수 없음. 

• 객체가 생성되지 않은 상태에서 non-static멤버는 만들어져 있지 않기 때문에

• 반대로, non-static 메소드에서 static 멤버에 접근 할 수 있음.

• static 메소드에서는 this 키워드 사용 불가

 

 

package java_first_project;

public class Number {
	
	// static 유무 차이
	public static int num1 = 0;
	public int num2 = 0;
	
	// changeNum1 스테틱 메소드인데 none-static 맴버인 num2에 접근할 수 없다.
	public static void changeNum1() {
		num2 = 1;
	}
	public void changeNum() {
		num1 = 1;
	}
	
}

cannot make a static referense to the none-static filed num2 라고 뜬다

스테틱 메소드가 none-static 맴버인 num2에 접근할 수 없다고 오류가 뜹니다.

 

 


실습 static 

위의 실습에서 인스턴스 갯수 추가 해보도록

정답