1. 클래스
1.1 클래스의 기본 개념
- 클래스는 메서드를 분류 및 데이터 타입 정의를 위해 사용한다.
- 메서드 분류 : 코드 유지보수성을 위해 사용
- 데이터타입 정의 : 기본 자료형외의 데이터 타입을 관리 하기 위해 사용한다. (User-defined Data Type)
2. 메서드 분류
2.1 클래스필드와 인스턴스필드
- 클래스 필드 : static필드 라고도 불리며 클래스 변수는 클래스당 1개만 존재
- 인스턴스 필드 : non-static필드 라고도 불리며 인스턴스 변수를 동적할당을 통해 여러개 생성
2.2 클래스필드
- 클래스 필드는 변수를 1개만 생성할 수 있다.
- static 필드를 사용한다.
- 클래스 필드의 형식
class Calculator{
static int result;
}
main(String[] args){
Calculator.result;
}
- 예제
- 클래스 필드는 클래스명.메서드(); 로 사용한다.
- 한번에 한개의 클래스만 사용 가능하다.
package study.oop.clazz;
public class Test01 {
public static void main(String[] args) {
Calculator.plus(2);
Calculator.plus(3);
Calculator.minus(1);
Calculator.multiple(7);
Calculator.divide(3);
System.out.printf("result = %d\n", Calculator.result);
}
}
- 클래스의 필드의 변수를 static으로 선언해야한다.
- static 메소드는 static으로 선언된 변수와 메서드만 접근 가능하다.
package study.oop.clazz;
public class Calculator {
static int result = 0;
static void plus(int a) {
result += a;
}
static void minus(int a) {
result -= a;
}
static void multiple(int a) {
result *= a;
}
static void divide(int a) {
result /= a;
}
}
2.3 인스턴스필드
- 인스턴스 필드는 new를 통해 Heap영역에 할당한 만큼 생성 가능하다
-인스턴스 필드는 non-static으로 선언한다.
- 인스턴스 필드의 형식
class Calculator{
int result = 0;
}
main(String[] args){
Calculator.c1 = new Calculator();
}
- 예제
- 인스턴스 필드는 클래스명 변수 = new 클래스명 (); 으로 선언한다.
- 객체가 인스턴스 된 후에 변수의 레퍼런스를 사용하여 메서드에 접근 한다.
package study.oop.clazz;
public class Test01 {
public static void main(String[] args) {
Calculator c1 = new Calculator();
Calculator.plus(c1, 2);
Calculator.plus(c1, 3);
Calculator.minus(c1, 1);
Calculator.multiple(c1, 7);
Calculator.divide(c1, 3);
System.out.printf("result = %d\n", c1.result);
}
}
- static 메서드에 접근을 하려면 static 필드의 변수나 메소드로 접근해야한다.
- static 메서드에 Calculator that의 레퍼런스를 넘겨 참조를 할 수 있게 한다.
package study.oop.clazz;
public class Calculator {
int result = 0;
static void plus(Calculator that, int a) {
that.result += a;
}
static void minus(Calculator that, int a) {
that.result -= a;
}
static void multiple(Calculator that, int a) {
that.result *= a;
}
static void divide(Calculator that, int a) {
that.result /= a;
}
}
2.3 this활용
- static 메서드를 접근 하려면 인스턴스 필드의 레퍼런스를 매개변수로 넘겨야한다.
- non-static 메서드를 선언하면 컴파일러 내부에서 this 레퍼런스를 생성하여 자동으로 넘긴다.
- this 참조는 객체 수준에서 접근 가능하다
- static으로 선언된 필드와 메소드는 클래스 단위에서 생성 되기 때문에 접근 불가하다.
- ex) Cal c1, Cal c2에서 this는 각각 c1,c2의 레퍼런스를 의미 하지만
- ex) static은 Cal을 의미하므로 this로 접근 할 수 없다.
package study.oop.clazz;
public class Calculator {
인스턴스 필드 생성
클래스 필드 생성
인스턴스 메서드 생성 -> this 포인터로 참조가능
클래스 메서드 생성 -> 클래스 필드로 접근(this 포인터로 접근 불가)
}
- 예제
package study.oop.clazz;
public class Test01 {
public static void main(String[] args) {
Calculator c1 = new Calculator();
c1.plus(2);
c1.plus(3);
c1.minus(1);
c1.multiple(7);
c1.divide(3);
System.out.printf("result = %d\n", c1.result);
}
}
package study.oop.clazz;
public class Calculator {
int result = 0;
void plus(int a) {
// c1의로 객체가 인스턴스 된다면
// c1객체의 레퍼런스가 this
// c1.result와 동일
this.result += a;
}
void minus(int a) {
this.result -= a;
}
void multiple(int a) {
this.result *= a;
}
void divide(int a) {
this.result /= a;
}
}
3. 데이터 타입 정의(User-define Data Type)\
3.1 데이터 타입을 만드는 이유
- 데이터 타입을 정의 하지 않으면, 서로 다른 타입의 자료형을 중복해서 사용해야한다.
- 코드의 유지보수 측면에서 비효율적이다.
package com.eomcs.oop.ex02.step11;
// 데이터 타입 정의
// 1) 클래스 사용전: 낱개 변수 사용
//
public class App {
public static void main(String[] args) {
String name;
int kor;
int eng;
int math;
int sum;
float aver;
name = "홍길동";
kor = 100;
eng = 90;
math = 85;
sum = kor + eng + math;
aver = (float) sum / 3;
System.out.printf("%s: %d, %d, %d, %d, %.1f\n", name, kor, eng, math, sum, aver);
name = "임꺽정";
kor = 90;
eng = 80;
math = 75;
sum = kor + eng + math;
aver = (float) sum / 3;
System.out.printf("%s: %d, %d, %d, %d, %.1f\n", name, kor, eng, math, sum, aver);
name = "유관순";
kor = 80;
eng = 70;
math = 65;
sum = kor + eng + math;
aver = (float) sum / 3;
System.out.printf("%s: %d, %d, %d, %d, %.1f\n", name, kor, eng, math, sum, aver);
}
}
3.2 클래스 만들기
- 위 코드에서 name,kor,eng,math,sum, aver, printf를 중복해서 사용한다.
- 이를 해결하기 위해 아래와 같은 클래스를 만든다.
package study.oop.clazz;
public class Score {
String name;
int kor;
int eng;
int math;
int sum;
float aver;
}
- 클래스를 만들고 객체를 인스턴스 한다.
- 객체 정의 타입은 주로 인스턴스 클래스를 사용한다. (여러객체를 인스턴스 해야하기 때문)
package study.oop.clazz;
public class Test02 {
public static void main(String[] args) {
Score s1 = new Score();
s1.name = "홍길동";
s1.kor = 100;
s1.eng = 90;
s1.math = 85;
s1.sum = s1.kor + s1.eng + s1.math;
s1.aver = (float) s1.sum / 3;
System.out.printf("%s: %d, %d, %d, %d, %.1f\n", s1.name, s1.kor, s1.eng, s1.math, s1.sum,
s1.aver);
Score s2 = new Score();
s2.name = "임꺽정";
s2.kor = 90;
s2.eng = 80;
s2.math = 75;
s2.sum = s2.kor + s2.eng + s2.math;
s2.aver = (float) s2.sum / 3;
System.out.printf("%s: %d, %d, %d, %d, %.1f\n", s2.name, s2.kor, s2.eng, s2.math, s2.sum,
s2.aver);
Score s3 = new Score();
s3.name = "유관순";
s3.kor = 80;
s3.eng = 70;
s3.math = 65;
s3.sum = s3.kor + s3.eng + s3.math;
s3.aver = (float) s3.sum / 3;
System.out.printf("%s: %d, %d, %d, %d, %.1f\n", s3.name, s3.kor, s3.eng, s3.math, s3.sum,
s3.aver);
}
}
3.3 메서드 정의
- 클래스로 객체를 정의하면 여러 메서드에 있어 장점이 생긴다
- 위의 코드에서 sum,aver,printf는 같은 형식을 사용 하고 있으므로, 메서드로 변형을 한다.
package study.oop.clazz;
public class Test02 {
public static void main(String[] args) {
Score s1 = new Score();
s1.name = "홍길동";
s1.kor = 100;
s1.eng = 90;
s1.math = 85;
compute(s1);
printScore(s1);
Score s2 = new Score();
s2.name = "임꺽정";
s2.kor = 90;
s2.eng = 80;
s2.math = 75;
compute(s2);
printScore(s2);
Score s3 = new Score();
s3.name = "유관순";
s3.kor = 80;
s3.eng = 70;
s3.math = 65;
compute(s3);
printScore(s3);
}
static void compute(Score s) {
s.sum = s.kor + s.eng + s.math;
s.aver = (float) s.sum / 3;
}
static void printScore(Score s) {
System.out.printf("%s: %d, %d, %d, %d, %.1f\n", s.name, s.kor, s.eng, s.math, s.sum, s.aver);
}
}
- compute 메서드는 Score의 객체안에서 수행할 수 있는 기능으로 Score로 이동한다.
- 이때 non-static 변수로 전환여 인스턴스된 객체의 this 레퍼런스를 사용한다.
package study.oop.clazz;
public class Score {
String name;
int kor;
int eng;
int math;
int sum;
float aver;
void compute() {
this.sum = this.kor + this.eng + this.math;
this.aver = (float) this.sum / 3;
}
}
//main 코드
//compute(s) ->s.compute();로 변경
3.4 접근지정자
- 패키지 이동
- Score 클래스는 메인 클래스의 형태와 계산을 보조하는 역할로 패키지를 구분 하여 준다.
기존 변경 --study
|- oop.clazz
|- Test02.java
|- Score.java--study
|- oop.clazz
|- vo(dto)
| |- Score.java
|- Test02.java
- 접근지정자
- 패키지가 달라지면 접근지정자에 따라 클래스에 접근하는 방법도 달라진다.
- 접근 등급을 나누어 클래스파일에 권한을 설정 하는 지정자를 접근 지정자라고 한다.
접근 지정자 | 현재 클래스 내부 | 동일 패키지 내부 | 하위 클래스 내부 | 전체적인 접근 가능 |
public | O | O | O | O |
protected | O | O | O | X |
(default,생략) | O | O | X | X |
private | O | X | X | X |
- Scored와 Test02의 패키지가 달라졌으므로 public 접근 지정자를 사용하여한다.
3.5 생성자
- 객체를 인스턴스하면 자동적으로 생성자가 생성된다.
- 객체 오버로딩을 통해 다른 타입의 생성자를 여러개 호출 할 수 있다.
package study.oop.clazz.vo;
public class Score {
public String name;
public int kor;
public int eng;
public int math;
public int sum;
public float aver;
// 기본생성자
public Score() {}
// 생성자 오버로딩
public Score(String name, int kor, int eng, int math) {
this.name = name;
this.kor = kor;
this.eng = eng;
this.math = math;
this.compute();
}
public void compute() {
this.sum = this.kor + this.eng + this.math;
this.aver = (float) this.sum / 3;
}
}
- 생성자를 오버로딩 하여 쓸 경우, main의 인스턴스 코드가 훨씬 간결 해진다.
package study.oop.clazz;
import study.oop.clazz.vo.Score;
public class Test02 {
public static void main(String[] args) {
Score s1 = new Score("홍길동", 100, 90, 85);
Score s2 = new Score("임꺽정", 90, 80, 75);
Score s3 = new Score("유관순", 80, 70, 65);
printScore(s1);
printScore(s2);
printScore(s3);
}
static void printScore(Score s) {
System.out.printf("%s: %d, %d, %d, %d, %.1f\n", s.name, s.kor, s.eng, s.math, s.sum, s.aver);
}
}
3.6 인스턴스 필드 접근 제한
- 접근지정자를 public으로 설정할 경우, 모든 클래스 파일에서 필드 값을 수정 할 수 있다.
- 이는 코드의 기초 데이터를 흔들기 때문에 접근지정자를 통해 접근을 제한하는 것이 좋다.
- 필드의 변수들의 접근은 인스턴스 메소드를 통해 접근 하는 것이 코드의 유지 보수성이 좋아진다.
- setter()에서 값을 다시 받으면 합계와 평균은 다시 계산 해주어야하기 때문에 compute()메서드를 추가한다.
package study.oop.clazz.vo;
public class Score {
private String name;
private int kor;
private int eng;
private int math;
private int sum;
private float aver;
// 기본생성자
public Score() {}
// 생성자 오버로딩
public Score(String name, int kor, int eng, int math) {
this.name = name;
this.kor = kor;
this.eng = eng;
this.math = math;
this.compute();
}
public void setName(String name) {
this.name = name;
}
public void setKor(int kor) {
this.kor = kor;
this.compute();
}
public void setEng(int eng) {
this.eng = eng;
this.compute();
}
public void setMath(int math) {
this.math = math;
this.compute();
}
public String getName() {
return this.name;
}
public int getKor() {
return this.kor;
}
public int getEng() {
return this.eng;
}
public int getMath() {
return this.math;
}
public int getSum() {
return this.sum;
}
public float getAver() {
return this.aver;
}
public void compute() {
this.sum = this.kor + this.eng + this.math;
this.aver = (float) this.sum / 3;
}
}
- 메인 코드
package study.oop.clazz;
import study.oop.clazz.vo.Score;
public class Test02 {
public static void main(String[] args) {
Score s1 = new Score("홍길동", 100, 90, 85);
Score s2 = new Score("임꺽정", 90, 80, 75);
Score s3 = new Score("유관순", 80, 70, 65);
printScore(s1);
printScore(s2);
printScore(s3);
}
static void printScore(Score s) {
System.out.printf("%s: %d, %d, %d, %d, %.1f\n", s.getName(), s.getKor(), s.getEng(),
s.getMath(), s.getSum(), s.getAver());
}
}
'개발자 꿈나무의 하루 > 01_Boot Camp' 카테고리의 다른 글
(네이버클라우드 부트캠프) 18일차 - 실습프로젝트(게시판CRUD) (0) | 2024.06.19 |
---|---|
(네이버클라우드 부트캠프) 17일차 - 실습프로젝트(CRUD구현하기) (0) | 2024.06.18 |
(네이버클라우드 부트캠프) 15일차 - 실습프로젝트(클래스) (1) | 2024.06.14 |
(네이버클라우드 부트캠프) 14일차 - 실습프로젝트(서브메뉴만들기) (1) | 2024.06.13 |
(네이버클라우드 부트캠프) 13일차 - Java프로그래밍 기초(메서드) (0) | 2024.06.12 |