본문 바로가기
Study/JAVA

[JAVA] 3주차_자바 문법과 객체 지향 (제어문과 메서드, 객체지향프로그래밍 개요, 접근자와 설정자)

by 8희 2022. 3. 20.

1차시 제어문과 메서드

 


제어문: 제어문은 실행문의 수행 순서를 변경 (if문, while문, for문)

/* if-else 문을 이용한 홀짝 조사 */

import java.util.Scanner; //Scanner 클래스의 경로 이름을 컴파일러에 알림

public class IfElseDemo {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in); //Scanner 객체 색성 (1)
		System.out.print("숫자를 입력하세요 : "); //(2)
		int number = in.nextInt(); //데이터 입력 받기 //(3)

		if (number % 2 == 0) 
			System.out.println("짝수!");
		else
			System.out.println("홀수!");
		System.out.println("종료");
        
        //System.out.println( (number%2 == 0)?"짝수!" : "홀수!" ); //조건 연산자 사용 가능
        //in.close(); //생성한 Scanner 객체 소멸
	}
}

(1)과 (2)의 순서 바뀜 -> 오류 발생 X 

(1)과 (3)의 순서 바뀜 -> 오류 발생 O

 

자바에서 키보드로 데이터 입력을 받기 위해선 4단계를 거쳐야 한다. 

1. Scanner 클래스의 경로 이름을 컴파일러에 알리기 import java.util.Scanner;

2. System.in 객체와 연결된 Scanner 객체 생성 Scanner in = new Scanner(System.in);

3. Scanner 클래스가 제공하는 다양한 메서드를 이용해 키보드로 데이터 입력 받기 int x = in.nextlnt();

4. 생성한 Scanner 객체 소멸 in.close();

 

(2)는 데이터 출력에 해당하기에 (1)과 순서가 바뀌어도 상관이 없지만, (3)은 데이터 입력에 해당하므로

(1)과 순서가 바뀌는 경우 오류가 발생한다! (1)이 선언되어야 (3)을 사용할 수 있는 것이다.

 


메서드: 수행할 작업을 나열한 코드의 모임 (c언어에서의 함수와 동일한 의미)

 

메서드의 필요성과 장점

1. 중복 코드 줄여 코드 재사용 

2. 가독성 높여 프로그램의 품질 향상

 

/* 메서드에서 return문 활용 */

public class ReturnDemo { //이게 메서드
	public static void main(String[] args) {
		printScore(99); //메서드 호출
		printScore(120); //메서드 호출
	}

	public static void printScore(int score) {
		if (score <= 0 || score >= 100) {
			System.out.println("잘못된 점수 : " + score);
			return;
		}
		System.out.println("점수 : " + score);
	}
}

미리 공간 확보를 하고 있는 것이므로 printScore 메서드도 static으로 선언해야 한다.


메서드 시그니처: 메서드 이름과 매개변수의 개수, 데이터 타입, 순서를 의미

메서드 오버로딩: 메서드 이름은 같고 메서드 시그니처가 다른 메서드를 정의하는 것

/* 메서드와 값 전달 - 메서드 호출에서 값 전달의 의미 */

public class IncrementDemo {
	public static void main(String[] args) {
		int x = 0;
		System.out.println("increment() 메서드를 호출하기 전의 x는 " + x);
		increment(x); //함수가 실행될 때 x값 복사
		System.out.println("increment() 메서드를 호출한 후의 x는 " + x);
	}

	public static void increment(int n) { //n이 바로  매개변수 시그니처
		System.out.println("increment() 메서드를 시작할 때의 n은 " + n);
		n++;
		System.out.println("increment() 메서드가 끝날 때의 n은 " + n);
	}
}

increment 함수를 호출할 때 x값을 n에 복사한 것이므로 함수가 종료되는 시점에 n이란 공간은 사라진다. 

따라서 x는 n의 증가 여부와 상관 없이 자기 자신을 그대로 유지한다.

-> 이게 바로 메서드 호출에서 값 전달!

c++에서 값에 의한 호출 개념을 생각하면 이해가 더 잘 될 듯 함.

 

/* 메서드 오버로딩 */

public class OverloadDemo {
	public static void main(String[] args) {
		int i1 = 3, i2 = 7, i3 = 10;
		double d1 = 7.0, d2 = 3.0;

		System.out.printf("max(%d, %d) = %d\n", i1, i2, max(i1, i2));
		System.out.printf("max(%.1f, %.1f) = %.1f\n", d1, d2, max(d1, d2));
		System.out.printf("max(%d, %d, %d) = %d\n", i1, i2, i3, max(i1, i2, i3));
	}

	public static int max(int n1, int n2) { //메서드 이름 동일
		int result = n1 > n2 ? n1 : n2;
		return result;
	}

	public static double max(double n1, double n2) { //메서드 이름 동일
		double result = n1 > n2 ? n1 : n2;
		return result;
	}

	public static int max(int n1, int n2, int n3) { //메서드 이름 동일
		return max(max(n1, n2), n3);
	}
}

위의 예제를 통해 메서드 오버로딩을 쉽게 이해할 수 있다. 

예제에는 메서드 3개의 이름이 모두 max로 동일하지만 모두 잘 실행된다.

매개변수의 개수, 데이터 타입 등을 뜻하는 메서드 시그니처가 다르기 때문이다. 

즉, 다시 말해 메서드 오버로딩은 메서드 이름은 동일하지만 메서드 시그니처가 다른 것을 의미한다. 


2차시 객체지향프로그래밍 개요

 


객체(=인스턴스): 필드(상태) + 메서드(동작),

필드는 객체 내부에 선언된 변수를 뜻하고 메서드는 객체 내부에 정의된 동작을 뜻한다.

 

클래스와 객체: 클래스는 미리 보기, 객체는 메모리 상에 올라가 있는 실질적인 정보

인스턴스화: 클래스를 이용하여 객체를 만드는 것

 

객체 지향 프로그래밍:

현실 세계를 객체 단위로 프로그래밍하며 객체는 필드(데이터)와 메서드(코드)를 하나로 묶어 표현


객체 지향 프로그래밍의 특징

 

1. 캡슐화(정보 은닉):

- 관련된 필드와 메서드를 하나의 캡슐처럼 포장해 세부 내용을 외부에서 알 수 없도록 감추는 것

- 즉 데이터(= 상태 = 필드)를 은닉하는 것

- 공개 / 비공개 모드와 상속 모두 가능

 

2. 상속:

- 상위 객체를 상속받은 하위 객체가 상위 객체의 메서드와 필드를 사용하는 것

- 객체를 재사용하는 방법 중 하나

- 확장이 가능한 상태

 

3. 다형성:

- 대입되는 객체에 따라서 메서드를 다르게 동작하도록 구현하는 기술

- 실행 도중 동일한 이름의 다양한 구현체 중에서 메서드를 선택 가능(ex. 메서드 오버로딩)


클래스의 선언

 

1. 추상화:

- 현실의 객체에서 불필요한 속성을 제거하고 중요한 정보만 클래스로 표현하는 일종의 모델링 기법

- 사람마다 추상화하는 기법이 같지 않으므로 각 개발자는 클래스를 다르게 정의 가능

 

2. 클래스의 선언 형식 예시

public class Ball { //클래스의 이름은 소스 파일 이름과 동일해야 함
	double radius = 2.0; //필드
    double getVolume { //메서드
    	return 4 / 3 * 3.14 * radius * radius * radius;
        }
 }

 

3. 객체 생성 형식

클래스이름 변수 = new 클래스 이름();

/* 클래스 선언과 객체 생성 - 소스 파일 이름 PhoneDemo */

class Phone {
	String model;
	int value;

	void print() {
		System.out.println(value + "만원 짜리 " + model + " 스마트폰");
	}
}

public class PhoneDemo { //소스 파일 이름과 같음
	public static void main(String[] args) {
		Phone p1 = new Phone(); //객체(p1) 생성
		p1.model = "AAAA"; //필드 값
		p1.value = 200; //필드 값
		p1.print(); //메서드 호출
		
		Phone myPhone = new Phone(); //객체 myPhone 생성
		myPhone.model = "갤럭시 S8";
		myPhone.value = 100;
		myPhone.print();

		Phone yourPhone = new Phone(); //객체 yourPhone 생성
		yourPhone.model = "G6";
		yourPhone.value = 85;
		yourPhone.print();
	}
}

main 메서드를 갖는 클래스에만 public이 붙는다.

 


3차시 접근자와 설정자

 


기초 타입과 참조 타입

- 자바의 데이터 타입은 기초 타입과 참조 타입으로 나뉜다.

- 기초 타입은 기본 데이터 타입으로 정수, 문자, 실수, 논리 타입을 의미한다. (ex. byte, short, int, char, float 등)

- 참조 타입객체적 개념으로 배열, 열거, 클래스, 인터페이스 타입을 의미한다.

int ten = 10; //기초 타입
Ball myBall = new Ball(); //참조 타입 //새롭게 할당된 Ball 객체의 주소가 myBall에 들어감
Ball yourBall = new Ball(); //참조 타입 //새롭게 할당된 Ball 객체의 주소가 yourBall에 들어감
yourBall = myBall; //yourBall에 myBall의 주소를 넣게 되면 손실되는 값 발생

 

필드와 지역 변수

/* 지역 변수의 사용 범위 */

public class LocalVariableDemo {
	public static void main(String[] args) {
		int a = 0; //지역변수 //a는 초기화 O
		double b; //지역변수 //b는 초기화 X

		// System.out.print(b); //(1)
		// System.out.print(a + c); //(2)

		int c = 0;

		// public double d = 0.0; //(3)

		for (int e = 0; e < 10; e++) {
			// int a = 1; //(4)
			System.out.print(e);
		}
	}
}

 

 

클래스 영역에 선언된 변수: 필드, 전역 변수, 멤버 변수 (클래스 범주 안에 있으면 public으로 지정 가능)

메서드 내부에 선언된 변수: 지역 변수 (매개변수도 일종의 지역 변수)

 

- 필드는 선언되면서 자동으로 초기화되지만, 지역 변수반드시 초기화를 해야 한다!

- 지역 변수는 블록이 달라도 같은 이름으로 다시 선언할 수 없다.

 

(1) 오류 발생: 초기화되지 않고는 사용할 수 없다.

(2) 오류 발생: 변수 c는 아직 선언되지 않았기 때문에 사용할 수 없다.

(3) 오류 발생: 지역 변수는 public으로 지정할 수 없다.

(4) 오류 발생: 블록이 달라도 같은 이름으로 다시 선언할 수 없다.

 

클래스 내부에서 멤버 접근: (꼭 static으로 선언되어야 함)

- 같은 범위 내에 있으므로 필드 이름을 그대로 사용 가능 (ex. return * radius;)

- 같은 클래스 내부에서 호출하므로 메서드 이름을 그대로 사용 가능 (ex. findArea();)

 

클래스 외부에서 멤버 접근

- 클래스끼리는 서로 독립된 영역이므로 필드나 메서드에 접근하기 위해선 객체 필요

- 객체 생성 후 .을 붙여 접근 가능 (ex. myCircle.radius = 10.0;)

 


접근자와 설정자

- 클래스 내부에 캡슐화된 멤버를 외부에서 사용하기 위해서 필요

- 일반적으로 접근자는 get, 설정자는 set으로 시작하는 이름 사용

- 필드 이름을 외부와 차단해서 독립시키기 때문에 필드 이름 변경이나 데이터 검증도 가능

- 접근자는 필드의 값을 반환하는 메서드, 설정자는 필드의 값을 설정하는 메서드

public class CircleDemo {
	public static void main(String[] args) {
		Circle myCircle = new Circle();

		myCircle.setRadius(10.0);

		myCircle.show(myCircle.getRadius(), myCircle.findArea());
	}
}

class Circle {
	private double radius;

	public double getRadius() { //접근자
		return radius;
	}

	public void setRadius(double r) { //설정자
		this.radius = r;
	}

	double findArea() {
		return 3.14 * radius * radius;
	}

	void show(double x, double y) {
		System.out.printf("반지름 = %.1f, 넓이 = %.1f\n", x, y);
	}
}

 

생성자 

- 객체를 생성하는 시점에서 필드를 다양하게 초기화

- 생성자의 선언 방식: 클래스 이름 (...) {...}

- 생성자 이름 = 클래스 이름, 생성자의 반환 타입 X

- 생성자는 new 연선자와 함께 사용하며, 객체를 생성할 때 호출

- 생성자도 오버로딩 가능

- 기본 생성자: (매개변수가 없는 생성자)

모든 클래스는 최소한 하나의 생성자가 있다. 생성자를 선언하지 않으면 컴파일러가 기본 생성자를 자동으로 추가

생성자를 하나라도 만든다면 기본생성자 자동으로 추가 X

 

오버로딩: 1개의 클래스에서 동일한 이름의 메소드 또는 생성자를 여러 개 정의하는 것

메서드 오버로딩 설명 참고

public class CircleDemo {
	public static void main(String[] args) {
		Circle myCircle = new Circle(10.0); //(1) 생성자 존재 -> 사용 가능
		// Circle yourCircle = new Circle(); //(2) 기본 생성자가 없으므로 사용 불가능
	}
}

class Circle { //생성자를 만들었으므로 (1)은 실행 가능하지만, 기본 생성자가 만들어지지 않아 (2) 실행 불가능
	private double radius;

	public Circle(double r) {
		radius = r;
	}
}
/* 생성자 오버로딩 */

class Circle { //시그니처가 각각 다름
	double radius;
	String color;

	public Circle(double r, String c) { //생성자 이름 모두 동일
		radius = r;
		color = c;
	}

	public Circle(double r) {
		radius = r;
		color = "파랑";
	}

	public Circle(String c) {
		radius = 10.0;
		color = c;
	}

	public Circle() { //기본생성자
		radius = 10.0;
		color = "빨강";
	}
}

public class CircleDemo {
	public static void main(String[] args) {
		Circle c1 = new Circle(10.0, "빨강");

		Circle c2 = new Circle(5.0);

		Circle c3 = new Circle("노랑");

		Circle c4 = new Circle(); 
	}
}