목차
- 객체 지향 프로그래밍
- 클래스, 객체
- 객체변수, 메서드
- 메서드
- 필요한 이유, 매개변수와 인수
- 입력값과 출력값(리턴값)
- return의 또다른 쓰임
- 값에 의한 호출과 객체에 의한 호출
- 퀴즈, 코테
객체 지향 프로그래밍
객체 지향 프로그래밍 ( Object-Oriented Programming, OOP )
- 클래스 하나만으로는 결괏값을 따로 유지할 수 없다.
- 같은 틀의 여러개의 객체를 생성해 코드를 효율적으로 관리하고, 가독성을 높인다고 이해하면 쉽다.
- 클래스를 여러 개 생성하기 보다 클래스 하나의 틀을 만들고 그 클래스의 객체를 여러 개 생성하는 식으로!
- 객체들은 다른 객체와는 상관없이 각각의 독립적인 값을 유지한다.
- 궁극적으로, OOP는 코드의 효율적인 관리와 개발 생산성 향상을 위해 필요한 방식이다.
클래스, 객체
- 객체(object)를 만드는 기능을 한다.
- [클래스이름] [객체이름] = new [클래스이름]();
- new는 객체를 생성할 때 사용하는 키워드
class Animal {
}
public class Sample {
public static void main(String[] args) {
Animal cat = new Animal();
}
}
➡️ ‘cat은 객체’ , ‘cat은 Animal의 인스턴스’
(인스턴스는 객체와 클래스의 관계를 명시할 때 쓰인다.)
Animal클래스로 무수히 많은 동물 객체들을 만들 수 있다.
객체 변수, 메서드
- 클래스에 선언된 변수를 객체 변수라고 한다.
- 객체 변수에 접근하려면 [객체].[객체변수]
- 메서드는 클래스 내에 구현된 함수를 말한다.
class Animal {
String name; // 객체 변수 선언
public void setName(String name) { // 메서드 생성
this.name = name; //현재 객체의 필드 name을 가리킴, name은 메서드의 매개변수를 가리킴
}
}
public class Sample {
public static void main(String[] args) {
Animal cat = new Animal();
cat.setName("boby"); //this.name은 cat객체의 필드인 name을 의미하게 됨
Animal dog = new Animal();
dog.setName("happy");
}
}
<같은 클래스에서 만든 객체 두개에서 같은 객체 변수를 호출할 때>
class Animal {
String name;
public void setName(String name) {
this.name = name;
}
}
public class Sample {
public static void main(String[] args) {
Animal cat = new Animal();
cat.setName("boby"); // 메서드 호출
Animal dog = new Animal();
dog.setName("happy");
System.out.println(cat.name); // body
System.out.println(dog.name); // happy
}
}
➡️ 객체 변수인 name인 공유되지 않는다!
➡️ 객체 변수의 값은 독립적으로 유지된다!!
( static을 이용하여 객체 변수를 공유하도록 만들 수도 있다. )
메서드
필요한 이유
- 여러 번 반복해서 사용될 때를 위해 한 뭉치로 묶어서 한 메서드를 작성하면 편리하다
- return은 메서드의 결괏값을 돌려주는 명령어이다
public class Sample {
int sum(int a, int b) {
return a + b;
}
public static void main(String[] args) {
int a = 3;
int b = 4;
Sample sample = new Sample();
int c = sample.sum(a, b);
System.out.println(c);
}
}
Sample 클래스의 main 메서드에서 Sample sample = new Sample()처럼 자기 자신의 객체를 생성했다. 이러한 방식이 좀 이상하게 보일수도 있지만 작성한 클래스를 단독으로 실행시켜 테스트할 때 자주 사용하는 방법이다.
매개변수와 인수
- 매개 변수(parameter)는 메서드에 전달된 입력값을 저장하는 변수
- 인수(arguments)는 메서드를 호출할 때 전달하는 입력값
public class Sample {
int sum(int a, int b) { // a, b 는 매개변수
return a+b;
}
public static void main(String[] args) {
Sample sample = new Sample();
int c = sample.sum(3, 4); // 3, 4는 인수
System.out.println(c);
}
}
메서드 구조, 분류
리턴자료형 메서드명(입력자료형1 매개변수1, 입력자료형2 매개변수2, ...) {
...
return 리턴값; // 리턴자료형이 void 인 경우에는 return 문이 필요없다.
}
입력값 O | 입력값 X | |
리턴값 O (리턴 자료형 표기) |
int sum(int a, int b) { return a+b; } Sample sample = new Sample(); int result = sample.sum(3, 4); 이때 result의 자료형은 sum 메서드의 리턴 자료형인 int로 해야한다. |
String say() { return "Hi"; } Sample sample = new Sample(); String a = sample.say(); System.out.println(a); // "Hi" 출력 |
리턴값 X (리턴 자료형 부분에 void라고 표기) |
void sum(int a, int b) { System.out.println(a+"과 "+b+"의 합은 "+(a+b)+"입니다"); } Sample sample = new Sample(); sample.sum(3, 4); // 3과 4의 합은 7입니다 |
void say() { System.out.println("Hi") } Sample sample = new Sample(); sample.say(); // Hi |
리턴값은 오직 return 명령어로만 반환이 가능하다
return으로 메서드 빠져나가기
특별한 경우 메서드를 빠져나가고 싶다면 return을 단독으로 사용하여 메서드를 즉시 빠져나갈 수 있다.
여기서 쓰인 return은 메서드를 호출한 곳에 리턴값을 돌려주는 역할이 아니라 메서드를 즉시 빠져나가는 역할을 한다.
1. return 문만 단독으로 사용하여 메서드를 빠져나가는 이 방법은 리턴 자료형이 void인 메서드만 가능하다. 리턴 자료형이 명시되어 있는 메서드에서 return 문만 작성하면 컴파일 오류가 발생한다.
2. return 문을 단독으로 사용하여 메서드를 빠져나가는 방법은 실제 프로그래밍에서 자주 사용한다.
public class Sample {
void sayNick(String nick) {
if ("바보".equals(nick)) {
return;
}
System.out.println("나의 별명은 "+nick+" 입니다.");
}
public static void main(String[] args) {
Sample sample = new Sample();
sample.sayNick("야호");
sample.sayNick("바보"); // 출력되지 않는다.
}
} // 나의 별명은 야호 입니다.
메서드 내에서 선언된 변수의 효력 범위
메서드 내에서 선언된 변수는 메소드 안에서만 쓰인다.
public class Sample {
void varTest(int a) {
a++;
}
public static void main(String[] args) {
int a = 1;
Sample sample = new Sample();
sample.varTest(a);
System.out.println(a);
}
}
// 1
그렇다면 varTest라는 메서드를 이용해서 main 메서드 외부의 a의 값을 1만큼 증가시킬 수 있는 방법은 없을까? 다음과 같이 varTest 메서드와 main 메서드를 변경해 보자.
public class Sample {
int varTest(int a) {
a++;
return a;
}
public static void main(String[] args) {
int a = 1;
Sample sample = new Sample();
a = sample.varTest(a);
System.out.println(a);
}
}
// 2
이렇게 메서드가 객체를 전달받으면 메서드 내의 객체는 전달받은 객체 그 자체로 수행된다
--> 입력으로 전달받은 sample 객체의 객체 변수 a의 값이 증가하게 되는 것
varTest 메서드의 입력 파라미터가 값이 아닌 Sample 클래스의 객체!!
- this를 활용해 객체에 접근 가능
public class Sample {
int a; // 객체변수 a
void varTest() {
this.a++;
}
public static void main(String[] args) {
Sample sample = new Sample();
sample.a = 1;
sample.varTest();
System.out.println(sample.a);
}
}
// 2
값에 의한 호출 VS 객체에 의한 호출
메서드에 객체를 전달할 경우 값만을 전달할 경우와 다르게 메서드에서 객체 변수의 값을 변경할 수 있다!
값 전달
class Updater {
void update(int count) {
count++;
}
}
class Counter {
int count = 0; // 객체변수
}
public class Sample {
public static void main(String[] args) {
Counter myCounter = new Counter();
System.out.println("before update:"+myCounter.count);
Updater myUpdater = new Updater();
myUpdater.update(myCounter.count);
System.out.println("after update:"+myCounter.count);
}
}
// before update:0
// after update:0
객체 전달
class Updater {
void update(Counter counter) {
counter.count++;
}
}
class Counter {
int count = 0; // 객체변수
}
public class Sample {
public static void main(String[] args) {
Counter myCounter = new Counter();
System.out.println("before update:"+myCounter.count);
Updater myUpdater = new Updater();
myUpdater.update(myCounter);
System.out.println("after update:"+myCounter.count);
}
}
// before update:0
// after update:1
이렇게 메서드의 입력으로 객체를 전달하면 메서드가 입력받은 객체를 그대로 사용하기 때문에 메서드가 객체의 속성값을 변경하면 메서드 수행 후에도 객체의 변경된 속성값이 유지된다.
퀴즈 (5.1 ~5.4장)
- 객체지향 프로그래밍(OOP)의 4대 특징이 아닌 것은?
- a) 상속
- b) 다형성
- c) 추상화
- d) 복사
- 클래스에서 필드와 메서드의 차이점은 무엇인가?
- a) 필드는 객체의 상태를 나타내고, 메서드는 동작을 정의한다.
- b) 필드는 동작을 정의하고, 메서드는 객체의 상태를 나타낸다.
- c) 필드와 메서드는 동일하다.
- d) 필드만 객체에 속한다.
- 다음 중 this 키워드의 역할은 무엇인가?
- a) 상속된 메서드를 호출한다.
- b) 현재 객체를 참조한다.
- c) 부모 객체를 참조한다.
- d) 외부 클래스의 필드를 참조한다.
- 클래스에서 this 키워드를 사용하는 이유는 무엇인가?
- a) 같은 이름의 지역 변수와 필드를 구분하기 위해
- b) 상속받은 필드를 참조하기 위해
- c) 메서드 오버라이딩을 위해
- d) 클래스를 상속하기 위해
- 메서드의 리턴 타입이 void인 경우, 메서드가 반환하는 값은?
- a) null
- b) 0
- c) 아무 값도 반환하지 않는다.
- d) -1
- 아래 코드에서 출력값은?
- public class Example {
int a = 5;
public void setA(int a) {
this.a = a;
}
public static void main(String[] args) {
Example ex = new Example();
ex.setA(10);
System.out.println(ex.a);
}
} - a) 5
- b) 10 -> 객체 자체를 호출하고 this로 a에 10을 할당했으니까 출력값이 10이 됨!
- c) 0
- d) 컴파일 에러
- public class Example {
- 매개변수(parameter)와 인자(argument)의 차이는 무엇인가?
- a) 매개변수는 메서드 정의 시 사용되고, 인자는 메서드 호출 시 전달된다.
- b) 인자는 메서드 정의 시 사용되고, 매개변수는 메서드 호출 시 전달된다.
- c) 매개변수와 인자는 동일한 의미이다.
- d) 매개변수는 클래스 정의 시 사용되고, 인자는 메서드 정의 시 사용된다.
- 메서드가 값을 반환하는 데 사용하는 키워드는?
- a) return
- b) break
- c) exit
- d) continue
- 메서드 내에서 선언된 변수의 효력 범위(scope)는?
- a) 클래스 전체
- b) 메서드 전체
- c) 메서드가 호출된 후에도 유지된다.
- d) 메서드 내에서만 유효하다.
- 자바에서 call by value의 의미는?
- a) 참조 값을 전달한다.
- b) 객체를 직접 전달한다.
- c) 값의 복사본을 전달한다.
- d) 값의 참조를 전달한다.
- 객체를 생성할 때 사용하는 키워드는?
- a) object
- b) this
- c) new
- d) create
- 다음 중 클래스 멤버에 해당하지 않는 것은?
- a) 필드
- b) 메서드
- c) 생성자
- d) 지역 변수
- 다음 중 지역 변수와 필드를 구분하는 올바른 방법은?
- a) 지역 변수는 this 키워드로 접근한다.
- b) 필드는 클래스 외부에서 사용할 수 없다.
- c) 지역 변수는 메서드 내에서만 사용된다.
- d) 필드는 메서드 내에서만 사용된다.
- 자바에서 기본 데이터 타입을 객체로 감싸는 클래스는?
- a) Wrapper 클래스
- b) Interface 클래스
- c) Collection 클래스
- d) Abstract 클래스
- 객체의 생성자를 호출하는 역할을 하는 것은?
- a) 메서드
- b) 필드
- c) 클래스
- d) new 연산자
- return 키워드는 언제 사용되는가? (중요)
- a) 메서드의 실행을 종료하고 값을 반환할 때
- b) 메서드의 실행을 반복할 때
- c) 메서드 실행을 일시 중지할 때
- d) 메서드 내부에서만 사용될 때
- call by reference는 무엇을 의미하는가?
- a) 값을 복사하여 전달한다.
- b) 객체의 참조를 전달한다.
- c) 기본 데이터 타입을 전달한다.
- d) 메서드를 복사한다.
서술형 문제
- 클래스와 객체의 차이점?
- 클래스는 모양틀, 객체는 모양틀로 만든 것(인스턴스)이라고 생각하면 됨
- this 키워드를 사용하는 이유?
- 현재 객체를 참조, 매개변수와 필드의 이름이 같을 때 이를 구분하기 위해 사용
- 매개변수와 인자의 차이점?
- 매개변수는 메서드 정의 시 사용, 인자는 메서드 호출 시 사용
- 필드와 지역 변수의 차이점을 설명하고, this 키워드가 사용되는 이유를 함께 설명하기.
- 필드는 클래스 내에서 선언, 객체의 상태를 나타냄, 지역 변수는 메서드 내에서 선언되어 메서드 안에서만 유효, this는 지역변수와 필드의 이름이 같을 때 객체의 필드를 명확히 지칭하기 위해 사용됨
- 자바에서 call by value와 call by reference의 차이?
- 전자는 값의 복사본을 전달, 후자는 참조값(주소)를 전달
- 메서드 내에서 선언된 변수의 효력 범위(scope)란?
- 해당 메서드 안에서만 유효
- 자바에서 생성자(constructor)의 역할?
- 객체를 생성할 때 필드를 초기화, 객체의 초기 상태를 설정하는 역할을 함
- 클래스에서 final 키워드를 사용하는 이유와 그 효과?
- final은 클래스, 메서드, 또는 변수를 변경할 수 없도록 하며, 상속, 재정의, 수정을 방지함
- 메서드가 return을 사용하는 이유와 반환되는 값을 처리하는 방법?
- 메서드를 종료하거나 값을 돌려주기 위해 사용하며, 반환된 값은 호출한 곳에서 저장하거나 활용할 수 있다.
- 객체를 생성하는 방법과 그 과정에서 new 연산자의 역할?
- new로 객체를 생성하고 메모리 할당과 객체 초기화를 담당한다.
- 클래스와 인터페이스의 차이점?
- 클래스는 구현을 포함하고, 인터페이스는 구현 없이 메서드 선언만 제공
- 다음 코드에서 this 키워드가 어떻게 동작하는지 설명하기
- public class Test {
int value; // 클래스 필드(=전역 변수)
public Test(int value) { // 이 value는 매개변수이자 지역변수(생성자 내에서만 유효)
this.value = value; // 매개변수로 받은 값을 현재 객체의 필드에 할당
}
}- 클래스 필드를 의미
- 생성자의 매개변수로 전달된 값을 의미
- public class Test {
- 지역 변수와 전역 변수의 차이점?
- 지역변수는 해당 메서드나 블록 내에서만 유효하며 그 범위를 벗어나면 소멸됨
- 전역변수는 클래스 내에서 선언된 변수이며, 객체의 속성을 나타냄, 클래스의 모든 메서드에서 접근할 수 있으며, 객체가 존재하는 동안 유지됨, 또한 클래스의 객체마다 고유한 값을 가질 수 있음
코테
1. https://school.programmers.co.kr/learn/courses/30/lessons/12906?language=java
2. 1번 변형 문제 (반드시 1번을 먼저 해결한 후, 풀어주세요!)
- 아래 코드는 1번 문제를 해결하기 위한 코드이다. 주어진 코드에서 class를 완성시켜 프로그램을 실행했을 때, 올바른 결과가 출력되도록 만드시오.
출력 결과: [1, 3, 0, 1]
import java.util.*;
class NumberFilter {
private List<Integer> numbers;
public NumberFilter(int[] numbers) {
this.numbers = new ArrayList<>();
for (int num : numbers) {
this.numbers.add(num);
}
}
public List<Integer> removeConsecutiveDuplicates() {
List<Integer> result = new ArrayList<>();
if (numbers.isEmpty()) {
return result;
}
result.add(numbers.get(0));
for (int i = 1; i < numbers.size(); i++) {
if (!numbers.get(i).equals(numbers.get(i - 1))) {
result.add(numbers.get(i));
}
}
return result;
}
}
public class Main {
public static void main(String[] args) {
int[] arr = {1, 1, 3, 3, 0, 1, 1};
NumberFilter numberFilter = new NumberFilter(arr);
List<Integer> filteredNumbers = numberFilter.removeConsecutiveDuplicates();
System.out.println(filteredNumbers); // [1, 3, 0, 1]
}
}