일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 백준#boj#12755
- 백준#BOJ#12865#평범한배낭
- 백준#BOJ#2615#오목
- 백준#boj#16932#모양만들기
- 백준#BOJ#14501#퇴사#브루트포스
- 백준#BOJ#8012#한동이는영업사원
- 백준#BOJ#1939#중량제한
- Today
- Total
순간을 성실히, 화려함보단 꾸준함을
5주차 과제: 클래스 본문
목표
자바의 Class에 대해 학습하세요.
학습할 것(필수)
- 클래스 정의하는 법
- 객체 만드는 방법(new 키워드 이해하기)
- 메서드 정의하는 방법
- 생성자 정의하는 방법
- this 키워드 이해하기
- (번외)Nested Class
과제(Optional)
- int 값을 가지고 있는 이진 트리를 나타내는 Node 라는 클래스를 정의하세요.
- int value, Node left, right를 가지고 있어야 합니다.
- BinrayTree라는 클래스를 정의하고 주어진 노드를 기준으로 출력하는 bfs(Node node)와 dfs(Node node) 메소드를 구현하세요.
- DFS는 왼쪽, 루트, 오른쪽 순으로 순회하세요.
클래스 정의하는 법
클래스란??
=- 변수(데이터,속성)과 메서드(행위)를 가지고 있는 집합을 뜻합니다.
class 키워드를 사용하여 선언하고 ,new 연산자를 통해 인스턴스를 할당합니다.
규칙
- 첫번째 글자는 숫자가 올 수 없습니다.
- '$,'_' 이외의 특수 문자는 사용할 수 없습니다.
- 자바 키워드는 사용할 수 없습니다.
- 하나 이상의 문자로 이루어져야 합니다.
public class 클래스이름{
}
*주의할점 : 파일이름과 동일한 이름의 클래스 선언에서만 public 접근 제한자를 붙일 수 있습니다.
따라서 한 파일 내 다수의 클래스를 선언할땐 파일이름과 같지 않은 클래스는 public 접근 제한자를 붙일 수 없습니다.
Person.java FIle
public class Person{
}
class Man{
}
컴파일시 Person.class Man.class 파일이 생성됩니다.
클래스는 크게 3가지의 구성요소를 가지고 있습니다.
- 필드(Field) : 데이터를 담을 수 있는 곳
- 메서드(Method) : 객체의 동작을 정의할 수 있는 곳
- 생성자(Constructor) : 객체를 생성할 때 초기화를 담당하는 곳
public class Person{
//필드
int age;
//생성자
Person(){...}
//메서드
void get_age(){...}
}
- 필드
- 객체가 가지고 있는 데이터를 의미
- 객체가 소멸되기 전까지 사용할 수 있습니다. - 메서드
- 객체의 동작을 정의할 수 있습니다.
- 메서드는 선언부(자료형,메서드 이름, 매개변수) 와 실행 블록으로 이루어져 있습니다. - 생성자
- 반드시 클래스 내부에 존재해야 하며, 다수의 생성자를 가질 수 있습니다.
- new 연산자를 이용하여 인스턴스를 생성할 수 있고, 이때 자동으로 디폴트 생성자가 호출이 됩니다.
- 메서드와 비슷한 형태를 가지고 있지만 리턴타입이 정의되어 있지 않습니다.
- 만약 생성자를 따로 정의하지 않는다면 컴파일러는 자동으로 디폴트 생성자를 바이트코드에 추가시킵니다.
객체 만드는 방법(new 키워드 이해하기)
new 키워드란?
- 인스턴스(객체)를 생성할 때마다 사용되는 키워드 이며 Java에서는 객체 변수가 실제 데이터가 아닌 데이터를 담고 있는 공간의 주소값(참조값)을 가지고 있다는 특징이 존재합니다.
new 는 클래스 타입의 인스턴스(객체)를 생성해 주는 역할을 수행합니다.
즉, new 키워드를 사용하여 인스턴스(객체)를 생성하면 Heap 영역에 데이터를 저장할 공간을 할당받은 후 그 공간에는 데이터를 담고 있는 주소값(reference value)를 객체에게 반환해 줍니다.
이후 생성자를 호출합니다.
$$클래스\ 객체\ 변수 = new\ 클래스();$$
public class Person{
int age;
public static void main(String[] args){
Person person = new Person(); //Person 객체 생성
}
}
메서드 정의하는 방법
메서드란?
- 특정 기능을 정의한 코드들의 집합을 뜻합니다. 선언부(자료형,메서드 이름,매개변수)와 실행 블록으로 이루어져 있습니다.
String regPerson(String name){
...
return retName;
}
메서드는 오버로딩(Overloading)과 오버라이딩(Overriding)이 가능합니다.
오버로딩이란?
- 두개 이상의 메서드가 같은 이름을 가지고 있으나 매겨변수의 수가 다르거나 자료형이 다른 경우를 뜻합니다.
오버라이딩이란?
- 상위클래스에서 정의되어져 있는 메서드와 동일한 메서드가 하위클래스에 재정의 하는 것을 의미합니다. 오버라이딩은 상속과 연관이 깊습니다.
생성자 정의하는 방법
생성자란?
- 객체를 생성할때 호출되는 것으로, 객체를 초기화 해주기 위해 처음으로 실행되는 메서드이다.
- 유일한 반환타입이 존재하지 않는 메서드이다.
- 반드시 클래스 이름과 같아야 합니다.
class Piter{
int age;
//생성자
Piter(){
age=25;
}
}
public class Person{
public static void main(String[] args){
Piter piter = new Piter();
System.out.println(piter.age); //25 출력
}
}
보시다시피 객체를 생성하면 자동으로 생성자를 호출하게된다.
만약 생성자를 따로 정의를 해주지 않더라도 컴파일러는 자동으로 생성자를 생성한다. 이를 디폴트 생성자라고 한다.
정리를 다시 해보면 생성자는 크게 3가지로 나눌 수 있다.
- 소스 o / 매개변수 o : 매개변수가 있는 생성자
- 소스 o / 매개변수 x : 매개변수가 없는 생성자(No-args 생성자)
- 소스 x / 매개변수 x : 소스로 정의가 되어있지도 않은 생성자(디폴트 생성자)
중요한 점은 디폴트 생성자는 No-args 생성자 이지만 결코 No-args 생성자는 디폴트 생성자가 아니라는 점이다.
//No-args 생성자
class Piter{
int age;
//생성자
Piter(){
age=25;
}
}
//디폴트 생성자
class Piter{
int age;
}
또한, 한가지 더 알아야 할 점은 상속과도 연관성이 깊은 내용이다. 자식클래스로 인스턴스(객체)를 생성할때 부모클래스의 생성자가 자동으로 호출된다는 점이다.
따라서 부모클래스의 생성자를 선언해 줄때 No-args 생성자를 생성해 주지 않으면 에러가 발생하는 것을 확인할 수 있다.
class Piter_Father{
int age;
Piter_Father(int age){...} //에러가 발생
}
class Piter extends Piter_Father{
int age;
Piter(){
age=25;
}
}
public class Person{
public static void main(String[] args){
Piter piter = new Piter();
}
}
먼저 Person 클래스의 main 함수에서 자식클래스인 Piter로 객체를 생성해 주었다. 그러면 당연하게 Piter의 생성자가 호출이 될것이다. 그러나 이 소스는 에러가 발생한다. 이유는 부모클래스의 생성자를 먼저 호출하기 때문이다.
현재 저 소스에는 No-args 생성자가 선언이 되어있지 않기 때문에 결국 에러가 발생하는 것이다.
class Piter_Father{
int age;
Piter_Father(){...} //No-args 생성자 추가
Piter_Father(int age){...}
}
class Piter extends Piter_Father{
int age;
Piter(){
age=25;
}
}
public class Person{
public static void main(String[] args){
Piter piter = new Piter();
}
}
이를 No-args 생성자를 매번 추가해 주며 해결할 수 있지만 이런 방법은 매우 비효율적이다.따라서 우린 super라는 키워드를 사용하여 이런 문제를 해결 할 수 있다.
class Piter_Father{
int age;
Piter_Father(int age){...}
}
class Piter extends Piter_Father{
int age;
Piter(){
super(55); //super 추가
age=25;
}
}
public class Person{
public static void main(String[] args){
Piter piter = new Piter();
}
}
super키워드는 부모를 의미하고 괄호() 값에 파라미터를 추가하여 부모클래스의 생성자를 호출한다. 이로써 발생했던 문제점을 해결할 수 있게되었다.
주의할 점은 super키워드는 반드시 자식생성자의 첫줄에 위치해야 된다는 점이다. 또한, 부모클래스의 생성자의 매개변수와 자료형을 동일시 해주어야 한다.
this 키워드 이해하기
this란?
- 객체,자기 자신을 나타내는 명령어를 뜻합니다.
크게 3가지 형태로 사용됩니다.
1) 매개변수와 클래스의 필드값의 이름이 동일할때
public class Person{
int age;
Person(int age){
this.age = age;
}
}
만약 this
키워드를 사용하지 않고 초기화를 해주려고 했다면 초기화가 정상적으로 적용이 되지 않습니다. 이유는 this
키워드를 사용하지 않는다면 매개변수 = 파라미터
라는 식을 가지게 됩니다.
2) 오버로딩 된 다른 생성자를 호출 하고 싶을때
public class Person{
int x,y;
Person(){
this(10,20);
}
Person(int x,int y){
this.x = x;
this.y = y;
}
}
//x=10,y=20 이 할당됨
주의할 점은 this
는 반드시 생성자의 첫번째줄에 위치해야 한다는 점 입니다.
3) 자신의 참조값을 리턴시키고 싶을때
public class Person{
int x;
Person(int x){
this.x=x;
}
Person retPerson(){
return this;
}
}
+코드블록과 생성자 초기화 방법
맴버변수를 초기화 할 수 있는 방법은 2가지가 있습니다.
- 초기화 블록
- 생성자 초기화
public class Init {
int x;
static int y;
//코드블록 초기화 방법
static
{
y=10;
}
{
x=5;
}
public static void main(String[] args) {
Init init = new Init();
System.out.println("x : " + init.x);
System.out.println("y : " + init.y);
}
}
이때 static
블록은 클래스가 로딩시 단 한번만 실행이 된다. 이를 유의하자
그럼 만약 초기화 블록 과 생성자 초기화를 둘다 동시에 사용하게 된다면 뭐가 우선순위가 높을까?
public class Init {
int x;
{
x=5;
}
Init(){
x=10;
}
public static void main(String[] args) {
Init init = new Init();
System.out.println("x : " + init.x); //10이 출력된다.
}
}
생성자가 초기화블록보다 높은 우선순위를 갖는다. 단, 결코 초기화 블록이 실행이 되지 않는게 아닙니다. 오버로딩 되는 것 입니다.
Nested Class 출처
Nested Class란?
- Class
안에 또 다른 Class
를 추가할 수 있습니다. 이를 Nested Class
라고 합니다. 크게 2가지로 나뉘는데 static nested class
와 inner class
로 나뉩니다.
Nested Class
를 사용하는 방법은바깥클래스 이름.내부 클래스 이름 = new 바깥클래스이름.내부 클래스 이름()
로 인스턴스를 생성할 수 있습니다.
public class OuterClass {
static class StaticNestedClass {...}
class InnerClass {...}
}
중첩 클래스는 이 중첩 클래스를 둘러 쌓고 있는 바깥 클래스의 맴버변수 입니다.
따라서 바깥 클래스의 필드에 얼마든지 접근이 가능합니다.
그러나 static nested class
는 필드에 접근을 할 수 없습니다.
static nested class
static nested class
는 바깥 클래스의 필드값에 직접적으로 접근 할 수 없습니다.
따라서 그 클래스의 객체 참조를 사용할 수 밖에 없습니다.
public class OuterClass{
public static class StaticNestedClass{...}
}
public class Main{
public static void main(Strin[] args){
OuterClass.StaticNestedClass staticNestedClass = new OuterClass.StaticNestedClass();
}
}
inner class
inner class
는 객체의 필드와 메서드에 바로 접근이 가능합니다.
그러나 바깥클래스의 맴버변수로 취급받으므로 static
키워드는 사용 불가합니다. 다만 final
키워드를 사용하면 가능합니다.
public class OuterClass {
public class InnerClass {
static int static_number = 10; // 컴파일 에러 발생
static final int static_final_number = 10; // 선언 가능
}
}
왜 static
키워드를 사용하면 안될까요?
그 이유는 바깥클래스에 대해 종속성을 가지고 있기 때문입니다. 바깥클래스의 인스턴스를 다수 생성했다고 하면, static_number
에 접근하려고 할때 어느 인스턴스의 static_number
값이 옳은 것 인지 알 수가 없기 때문입니다.
그러나 final
키워드를 사용하게 된다면 컴파일 시점에 결정이 되버리고 변경을 할 수 없는 상수가 되버리기 때문에 사용할 수 있게 됩니다.
public class OuterClass {
public class InnerClass {
}
}
public class Main {
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
}
}
{바깥 클래스의 이름}.this.{멤버 변수}
를 사용해서 바깥클래스의 맴버변수에 접근할 수 있습니다.
public class OuterClass {
private int number = 10;
public class InnerClass {
private int number = 20;
public void method(int number) {
System.out.println(number); // 5 이 출력됩니다.
System.out.println(this.number); // 20 이 출력됩니다.
System.out.println(OuterClass.this.number); // 10 이 출력됩니다.
}
}
}
public class Main {
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
innerClass.method(5);
}
}
과제
- int 값을 가지고 있는 이진 트리를 나타내는 Node 라는 클래스를 정의하세요.
- int value, Node left, right를 가지고 있어야 합니다.
- BinrayTree라는 클래스를 정의하고 주어진 노드를 기준으로 출력하는 bfs(Node node)와 dfs(Node node) 메소드를 구현하세요.
- DFS는 왼쪽, 루트, 오른쪽 순으로 순회하세요.
다음 포스팅에 내용을 담겠습니다.
'백기선님과 함께 하는 자바 스터디' 카테고리의 다른 글
6주차 과제: 상속 (0) | 2021.06.12 |
---|---|
5주차 과제 : 추가사항 (0) | 2021.06.06 |
4주차 과제: 제어문 (0) | 2021.05.30 |
3주차 과제: 연산자 (0) | 2021.05.16 |
2주차 과제: 자바 데이터 타입, 변수 그리고 배열 (0) | 2021.05.05 |