Computer/Java, Kotlin

Java Study 2일차 : 생성자, 객체 배열, 매개변수

kentakang 2018. 1. 6. 15:14
반응형

Java Study 2일차

생성자, 객체 배열, 매개변수


벌써 Java Study 수업이 2일차에 들어왔네요.

이 수업은 총 3일차 수업으로 자바의 기초만 잡고 넘어가는 수업입니다.

저는 금요일에 이미 수업을 마친 상태인데, 어쩌다 보니 2일차 게시글을 지금 작성하게 되네요 ㅎㅎ

그럼 지금부터 2일차 시작하겠습니다.



우선 Java에서는 C언어와 다르게 문자열을 바로 선언해서 사용할 수 있습니다.

String을 통해서 사용할 수 있는데요

위 사진과 같이

String s1 = "스트링을 선언합니다.";
String s3 = new String("이렇게도 선언할 수 있습니다.");

이렇게 String을 선언할 수 있습니다.

근데 String 자료형은 다른 자료형들과 약간 다른 점이 있네요?

int, double과 같은 자료형들은 소문자로 시작하는데, String 자료형은 대문자로 시작하네요!

맞습니다. 우리가 배웠던 것과 같이 String도 클래스입니다.

전 시간에 클래스 이름은 대문자로 시작한다는거 배웠었죠?

위 코드에서 s1을 선언하는 건 다른 자료형들과 비슷하지만,

s3를 선언할때는 어떤가요? 우리가 클래스를 선언할때와 같죠?

근데 약간 다른 점이 있네요.

package test1;

public class Test3 {
    public static void main(String[] args) {
        Chan c1 = new Chan();

        c1.setHeight(171);
        c1.setWeight(50);

        System.out.println("키 : " + c1.getHeight() + " 몸무게 : " + c1.getWeight());
    }
}

이 코드는 우리가 클래스를 만들고 선언할 때 사용했던 코드입니다.

보시면 String s3를 선언할때는 클래스 이름 뒤에 있는 괄호에 문자열이 들어가는데, Chan을 선언할때는 그냥 빈 괄호만 있죠?

여기서 생성자라는 개념이 나옵니다.

우리가 클래스를 만들때 생성자를 따로 만들어 두지 않고, 사용할때도 괄호를 비워두고 사용하면

가상 머신에서는 이 클래스에 생성자가 없다고 생각하고 기본 생성자라는 걸 생성해줍니다.

package test1;

public Class ClassTest {
	
	public ClassTest() {
		
	}

}

이런 식으로 비어 있는 기본 생성자 (Default Constructor)가 만들어지게 됩니다.

근데 이런 생성자는 왜 만드는 걸 까요?

보통 생성자는 객체 변수들을 초기화 할 때 사용합니다.

Person 클래스를 한번 만들어볼까요?

우선 Class를 만들기 전에 Class를 설계해봅시다.

사람이니까 이름이랑 나이가 필요할거구요,

이름과 나이를 정하는 메소드와, 가져 오는 메소드가 있으면 좋겠네요.

한번 만들어 보겠습니다.

package test1;

public class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

원래는 우리가 이런 식으로 만들었었죠?

우선 기본 생성자를 추가해주겠습니다.

package test1;

public class Person {
    private String name;
    private int age;

    public Person() {
        this.name = "unknown";
        this.age = 1;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

이런 식으로 추가해줄 수 있죠.

우리가 메소드를 통해 입력을 받기 전까지는 이름과 나이를 알 수 없으니 이름은 unknown, 나이는 1살로 정해줬습니다.

잠깐, 근데 꼭 메소드를 통해 입력 받아야 하나요? String 자료형처럼 만들면서 입력할 수는 없을까요?

당연히 가능하죠! 우리는 위 코드를 짜면서 기본 생성자를 만드는 법을 알았습니다.

저 생성자가 이제 정수나 문자를 받을 수 있게만 해주면 끝나겠네요?

우리는 메소드가 정수나 문자형을 받게 하는 법도 알고 있으니, 둘을 잘 합치면 가능하지 않을까요?

package test1;

public class Person {
    private String name;
    private int age;

    // 생성자 오버로딩
    public Person() {
        this.name = "unknown";
        this.age = 1;
    }

    public Person(String name) {
        this.name = name;
        this.age = 1;
    }

    public Person(int age) {
        this.name = "unknown";
        this.age = age;
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

그럼 이런 식으로 만들어 줄 수 있습니다.

여러가지 경우가 있으니 우리는,

문자만 들어올 때, 정수만 들어올 때, 문자와 정수가 함께 들어올 때 어떻게 처리할 지를 모두 만들어놨습니다.

이러한 과정을 생성자 오버로딩이라고 합니다.

이렇게 해주면 원래는 Setter 메소드를 이용해서 여러가지를 정해줬었어야 했는데, 

이제는 만들 때 그냥 지정해 줄 수 있으니 코드의 길이가 줄어들겠죠?

이러한 생성자는 우리가 객체 배열을 사용할 때 더 유용한데요,

이제 객체 배열을 배워보도록 하겠습니다.



하지만, 그 전에 우리는 자바에서 배열을 배운 적이 없죠?

위 사진의 코드는 정수 배열 a에 1, 2, 3, 4, 5를 추가한 뒤,

배열에 들어가 있는 값을 차례대로 출력해 주는 코드입니다.

근데 잠깐 배열을 선언할 때 C언어와 다른 점이 있죠?

한번 비교해볼까요?

package test1;

public class Test5 {
    public static void main(String[] args) {
        // int[] a = new int[5];
        int[] a = new int[] {1, 2, 3, 4, 5};

        for(int i = 0; i < a.length; i++) {
            System.out.println(a[i] + " ");
        }
    }
}

#include <stdio.h>

int main()
{
	int a[5] = {1, 2, 3, 4, 5};
	
	for(int i = 0; i < 5; i++)
	{
		printf("%d\n", a[i]);	
	}	
}











왼쪽 코드가 사진에 있는 Java의 코드고, 오른쪽 코드는 제가 같은 기능을 하는 코드를 C언어로 작성한 코드입니다.

언어의 특성 상 여러가지 부분이 다른데요 배열을 선언하는 부분을 보시면,

Java에서는 자료형의 이름 뒤에 배열을 뜻하는 []가 붙는데, C언어에서는 변수의 이름 뒤에 배열을 뜻하는 []가 붙죠?

이것이 가장 큰 차이점 입니다.

우리가 처음 변수 선언을 배울 때는 자료형 + 변수 이름 + 상수 와 같은 식으로 배우는데요,

그러면 배열은 자료형에 포함 되니 int 뒤에 오는게 맞죠? 하지만 C 언어에서는 변수의 이름 뒤에 배열이 붙습니다.

사실 Java에서도 변수 이름 뒤에 []를 붙이는 식의 배열은 이용 가능하지만,

이렇게 배운 거 자료형 뒤에 붙여서 배열을 사용하는게 더 낫겠죠?

나머지 밑에 있는 코드들은 기본으로 C언어를 배워두셨다면 이해가 쉬우실 거에요.

다만, 처음보는 함수가 하나 들어가있죠?

a.length는 배열의 크기를 return 해주는 함수입니다.

앞으로 우리가 배열을 이용해 반복문을 짤 때는 숫자로 크기를 적어주는 대신, 배열 이름.length와 같은 식으로 코드를 작성해 줄 예정입니다.

그럼 이렇게 배열을 알아봤으니, 객체 배열을 한 번 알아볼까요?



위에서 만들어 둔 Person 클래스를 이용해서 객체 배열을 이용한 코드를 작성해봤습니다.

위에서 말했듯이 배열의 경우에는 자료형 뒤에 []가 붙습니다.

그러면 우리가 정수 배열을 만들어줬던걸 참고해서, 클래스 이름 뒤에 []를 붙이면 되겠죠?

package test1;

public class PersonMain2 {
    public static void main(String[] args) {
        Person[] p = new Person[9];
    }
}

이런 식으로 만들어줬습니다. 기존 Class를 생성할때와 다른 점은 앞에 있는 Person 뒤에 배열을 뜻하는 []가 붙고,

뒤에 있는 Person에도 []가 붙었는데, 여기서는 안에 숫자가 들어있죠?

저 안에 들어있는 숫자는 배열의 크기를 의미합니다.

우리는 9의 크기를 가진 p라는 배열을 만들어준거죠.

이제 이 배열을 이용해서 트와이스 1~9번째 멤버를 만든 다음, 출력해볼까요?

package test1;

public class PersonMain2 {
    public static void main(String[] args) {
        Person[] p = new Person[9];

        for(int i = 0; i < p.length; i++) {
            p[i] = new Person("트와이스 " + (i + 1) + "번째 멤버");
        }

        for(int i = 0; i < p.length; i++) {
            System.out.println("이름 : " + p[i].getName() + " 나이 : " + p[i].getAge());
        }
    }
}

이런 식으로 코드를 작성할 수 있겠죠?

이제 우리는 생성자와 객체 배열을 통해서, 우리가 직접 9개의 객체를 만들지 않아도

배열을 통해서 만들어 주는 법을 배웠네요?

앞으로도 활용할 곳이 많은 개념이니 꼭 익혀두고 넘어가세요.

객체 배열은 선언할 때는 다른 배열들과 다르지만, 사용할 때는 변수 이름[인덱스] 와 같은 식으로 사용법이 같습니다.


이제 매개 변수를 이용하는 방법을 알아보도록 하겠습니다.

우리는 지금까지 배워온 내용들을 통해서 main 메소드를 선언하는 부분을 일부분 이해할 수 있었습니다.

package test1;

public class Test6 {
    public static void main(String[] args) {
    }
}

위의 코드에서 public은 우리가 배웠던 개념인 접근 제어자에서 나온 public이네요!

왜 public이 들어갈까요?

자바 코드는 JVM(자바 가상 머신)을 통해서 구동하기 때문에, 가상 머신에서 접근할 수 있어야 하겠죠?

따라서 모든 곳에서 접근할 수 있는 접근 제어자인 public을 사용한거구요.

void는 return 값이 없는 메소드니까 void를 사용한거구요.

main은 메소드 이름, String[] 은 우리가 []가 붙어 있으니 배열이네요?

String에 붙어 있으니 문자열 배열이겠네요!

그러면 문자열 배열 args를 받는 메소드라는건데.. args가 무슨 뜻일까요?

우리가 매개 변수를 배우면 args가 무슨 의미인 지 알고, 마지막 3일차에서는 static의 개념까지 배울 수 있습니다.

그럼 무슨 의미일까요? args가 매개변수라는 의미죠.

매개변수를 받아서 출력하는 프로그램을 만들어볼까요?

package test1;

public class Test6 {
    public static void main(String[] args) {
        if(args.length == 0) {
            System.out.println("매개변수가 없습니다."); // 매개변수가 없을 시 오류 처리
            return;
        }

        System.out.println(args[0]);
    }
}

이런 식으로 작성해줬습니다.

if문 부터 천천히 볼까요?

먼저 if문의 조건은 args 배열의 길이가 0이면 매개변수가 없다고 출력해주는 부분이네요.

매개 변수가 들어오지 않을 때 오류를 출력해주기 위한 예외 처리입니다.

그리고 그 밑에는 args 변수의 0번째 인덱스를 출력해주는 코드네요.

이 코드를 한번 IDE에서 실행해볼까요?



아직 매개변수를 넣어주지 않아서 그런지 없다고 뜨네요..

그럼 이제 매개 변수를 넣어주는 법을 알아볼까요?

이클립스에서 매개 변수를 사용하는 방법은,



우리가 실행할때 사용하는 실행 버튼 옆에 있는 화살표를 눌러주세요.

그 뒤에 Run Configurations를 눌러주시면 이런 창이 뜹니다.

여기서 매개 변수를 뜻하는 Arguments를 눌러주시면,



이렇게 매개 변수를 입력하는 창이 뜨게 됩니다.

여기서 Program Arguments에 안녕하세요 라고 입력한 뒤 Run을 눌러볼까요?


이렇게 매개 변수를 받아 안녕하세요 라고 뜨는 걸 볼수 있네요!

매개 변수는 String 배열이기 때문에, 콤마를 통해서 구분해서 여러 문자열을 넣어줄 수도 있습니다!

우리가 아직 Java에서 사용자 입력을 받는 법을 배우지 않았기 때문에 유용하게 이용할 수 있겠죠?

그래서 이제 다른 클래스를 import 해서 사용하는 법을 알아보겠습니다.

Java에서 제공해주는 클래스를 import 해서 사용자의 입력을 받는 법도 배울 수 있겠네요!

package test1;

import java.util.Scanner;

public class Test7 {
    public static void main(String[] args) {
    }
}

보면 package test1; 밑에 import가 들어간 거 보이시죠?

우리는 Scanner라는 Class를 이용하기 위해서 java.util.Scanner 라는 Class를 import 했습니다.

이제 Scanner를 이용하면 끝이겠죠?

package test1;

import java.util.Scanner;

public class Test7 {
    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        int a = s.nextInt();
        System.out.println(a);
    }
}

Scanner를 이용해서 정수를 입력받고 출력해주는 코드입니다.

우선 Scanner를 s라고 선언하고 Scanner 객체를 만들어주네요.

그런데 Scanner 객체를 만들때 System.in 이라는 걸 매개변수로 넣어주네요?

자세한 설명은 나중에 하고, 일단 매개변수로 넣는다는 걸 외워둡시다.

하지만 우리가 출력을 할때는 System.out 을 사용하는 걸 보면,

System.in 이면 입력이라는 걸 유추할 수는 있겠죠?


int a = s.nextInt();


부분은 정수형 변수 a를 선언하고 a의 값은,

스캐너를 통해 입력 받은 정수로 정한다는 의미입니다.

그 다음에 println 함수를 통해 a의 값을 출력해주네요.


우리가 앞으로 배워나갈 Java 프로그래밍은 대부분 이런식입니다.

다른 사람들이 제작해 놓은 Class를 이용하며, 해당 Class의 사용법을 배우면서 프로그래밍을 배우는 것이죠.

다른 Class 하나 더 배워볼까요?

package test1;

import java.util.HashSet;

public class Test8 {
    public static void main(String[] args) {
        HashSet hs = new HashSet();

        // 자료구조 기초 예제
        hs.add(1);
        hs.add(2);
        hs.add(3);
        hs.add(4);
        System.out.println(hs); // 자료구조에 들어가 있는 값 출력
        hs.add(2);
        System.out.println(hs); // 중복된 값은 한 번만 들어감
        System.out.println(hs.size()); // 자료구조의 크기 출력
    }
}

위에서 사용한 HashSet 클래스는 자료구조 클래스입니다.

다시 첫줄부터 살펴볼까요?

HashSet hs = new HashSet(); 부분은 HashSet 객체를 생성하고 선언해주는 부분이구요.

hs.add(1); 는 이름을 보니 자료구조에 추가해주는 부분 같네요.

중간에 hs를 출력하는 부분은 옆에 붙어 있는 주석을 보면 알 수 있듯이,

자료구조에 들어가 있는 값들을 출력해주는 코드구요.

그 밑에서 hs.add(2); 를 했는데 옆에 주석에는 중복된 값은 한 번만 들어간다고 써있네요.

hs에 중복되는 값은 한 번만 들어가는 것 같습니다.

그럼 코드들을 보면 출력값은 [1, 2, 3, 4] 겠네요.

마지막으로 hs.size(); 는 자료구조의 크기를 알려주는 함수인 것 같구요.


그럼 여기까지 배운 내용들로 로또 번호 프로그램을 한 번 만들어볼까요?

프로그램을 작성하기 전에 한 번 생각을 해보면,

로또 번호도 중복이 없고, 자료 구조도 중복이 없네요.

그럼 자료 구조를 활용해서 만들어줄 수 있곘죠?

package test1;

import java.util.HashSet;

public class Test8 {
    public static void main(String[] args) {
        HashSet hs = new HashSet();

        // 자료 구조를 통해 로또 프로그램을 만들어보자.
        while(hs.size() < 6) {
            hs.add((int)(Math.random() * 45 + 1));
        }

        System.out.println("당신의 로또 번호는 " + hs + " 입니다.");
    }
}

저는 이런 식으로 작성해줬습니다.

새로 보는 함수가 있다면 Math.random 인데요.

Math.random 함수는 0부터 0.9까지의 숫자를 return 해주는 함수입니다.

여기에 1을 더해주면 1부터 1.9까지 숫자가 되겠죠?

거기에 45를 곱한 뒤, 소수점을 버려서 1 ~ 45 범위의 랜덤한 숫자가 나오게 하는 코드입니다.

hs.add를 사용하니 중복 된 숫자도 없겠죠?



이렇게 결과가 나오네요.


Class를 import해서 사용하는 법까지 한번 배워봤습니다.

다음 3일차는 마지막 시간인데요,

3일차까지 듣고 나면 Java의 기초적인 부분은 모두 이해하셨다고 봐도 좋을 것 같아요!

긴 글 봐주셔서 감사합니다.

반응형