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();
}
}
'Study > JAVA' 카테고리의 다른 글
[JAVA] 9주차_추상 클래스와 인터페이스, 인터페이스의 상속, 인터페이스 구현과 타입 변환 (0) | 2022.05.01 |
---|---|
[JAVA] 7주차_추상 클래스와 인터페이스 (접근지정자, final과 객체의 타입 변환) (0) | 2022.04.14 |
[JAVA] 6주차_상속 (메서드 오버라이딩, 패키지와 부모 생성자, Triangle 클래스와 Member 클래스) (0) | 2022.04.08 |
[JAVA] 5주차_동적배열과 상속 (동적배열과 객체배열, 상속, Rectangle 클래스, OddEven 클래스) (0) | 2022.04.03 |
[JAVA] 4주차_정적멤버, 문자열, 배열 (this와 정적멤버, 문자열, 배열) (0) | 2022.03.25 |