다섯째 날

정혅·2024년 2월 13일

더 조은 아카데미

목록 보기
7/76

메소드 정의 복습(개념만)

class Test
{
    public static void main(String[]args) 
    {
    }
}
  • args: 변수의 의미로 마음대로 사용 가능 > 그래도 왠만하면 args로 사용

  • String: 문자열을 사용한다는 의미다.

  • void: 반환하는 값이 없음

class Test //class이름과 파일 명이 다르면 x 
{
    public static void main(String[]args) 
    {
        System.out.println(hi(3)); //3의 자리는 argument = 인수 라고 한
    }
    public static void hi(int num) //항상 자료형을 붙여서 변수 작성 (두개여도)
    {
        System.out.println("Hi");
}
  • 파일을 .java로 저장 / 컴파일 하면 class뒤의 변수명으로 class파일 생성

    • 파일명과 class명은 항상 일치시켜서 저장
  • 매개변수는 수가 몇개든 각각의 자료형을 앞에 붙여줘야한다.


메소드를 만들어 1~100사이의 모든 소수 출력

public static void main(String[] args) {

        for(int i = 1; i <= 100; i ++) {

            if(isPrimeNumber(i))

                System.out.println(i + " ");

        }
    }
    public static boolean isPrimeNumber(int num) {

        if(num <= 1) return false;
        for(int i = 2; i < num; i++) {

            if(num % i == 0) return false;

        }
        return true;
    }
}

재귀 메소드(Recursive Call)

자기 자신을 호출

반복문을 사용하는 것보다 재귀 메소드를 사용하는 편이 더 직관적으로 이해하기 쉬울 때만 한정적으로 사용한것이 좋다.

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

        System.out.println("Start");
        reHi(3);
        System.out.println("End");
    }
    public static void reHi(int num) {
 //void일때 main메소드에서 출력하는 문장 안에 호출 못함 혼자 따로 해줘야함 
//System.out.println(reHi(3)); > 이렇게 하면 에러남 reHi(3); 이렇게 해야함 

        if(num == 0) return;//종료구간 생
        System.out.println("Hi");
        reHi(num - 1); //자기 자신을 호출 - 2 > 1 가지고 다시 처음으로, 
        System.out.println("Bye");
    }
}//Start > Hi 3번 Bye 3번 End로 종료 
  • return 뒤 반환값이 없어도 사용 가능하다 > void만 가능 자료형 사용해 반환하면 x

    • return을 만나면 호출한 곳으로 돌아간다.

      • num 1 이였을 때reHi(num-1)에서 호출했기 때문에 여기로 돌아가 Bye출력 > 종료

      • 종료 > num2 였을때 reHi(num-1)에서 호출했었기 때문에 이곳으로 돌아가 Bye출력

      • num3이였을때 reHi(num-1)에서 호출했었기 때문에 이곳으로 돌아가 Bye출력

  • reHi(num - 1); 이렇게 reHi(); 메소드안에서 본인을 호출하면 메소드 처음으로 돌아가 Hi가 0 과 같아질 때 까지 실행된다.

    reHi--; 이렇게 연산을 사용하면 무한루프이므로 조심

    이 식에서는 if문을 이용해 return되게 되어있어서 괜찮지만


퀴즈 - 재귀 메소드

Q1.Factorial을 재귀메소드로

class Q1{
public class ExTest {
    public static void main(String[] args) {

        System.out.println(factorial(5));

    }
    public static int factorial(int num) {

        if(num == 1) return 1; //num 이 1이 되었을때 1로 return 
         return num * factorial(num - 1);
    }//fac(5-1(=4)) > fac(4-1(=3)) > fac(3-1(=2)) > fac(2-1(=1)): 여기서 return
}//역순으로 돌아가기 때문에 fac(2-1(=1))*1 > fac(2)*1 > fac(3)*2 > fac(4)*6 > fac(5)*24로 return값을 갖고 돌아
  • 5! = 54! / 4! = 4 3! / 3! = 3 * 2!

  • num * num-1이 결국에는 factorial의 식이 되는것

    • return num * factorial(num - 1)이 5 * f(4)가 되고 > f(4)로 인해 다른 factorial로 이동해 밑에 문장처럼 진행

    • 4 f(3)이 되고 이를 반복해 1 f(0) 이 되는데 0이 되면 return되서 호출한 2*f(1)인 곳으로 돌아가 계산이 되는 알고리즘

  • return 1;인 이유는 제일 마지막인 1! (factorial)이 1이기때문에 return값을 1해준것이


Q2. 1부터 n까지의 합을 재귀메소드로 구현

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

            System.out.println(method(10));
        }     
        public static int method(int num) {

            if(num == 1) //종료되는 조건을 세우지 않으면 무한 루프 
            return 1;
        return num + method(num - 1);
    }
 }

Q3. 정수 n을 전달 받아서, 2의 N승을 계산하여 반환하는 메소드를 재귀의 형태로 정의할 것.

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

        System.out.println(multiple(4));
    }

    public static int multiple(int num) {

        if (num == 0)
            return 1;

        return multiple(num - 1) * 2;
    }
}

Q4.10진수 정수를 전달받아서, 전달받은 정수에 해당하는 2진수를 출력하는 메소드를 재귀의 형태로 정의

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

        binary(10);
    }

    public static void binary(int num) {
        if (num == 0)
            return;
        binary(num / 2);
        System.out.print(num % 2);
    }
}
  • void 를 사용한 사용자 정의 함수는 호출할때 println(); 속에 사용할 수 없다.
class tQ4{ //선생님 코드 
    public static void main(String[]args){
    binaryNum(10);
    }
    public static void binaryNum(int num){
    if(num < 2) System.out.print(num) //1과0으로 떨어지기때문에 2 이하면 출력이나 return되게끔 
    else{
        binaryNum(num/2);
        System.out.println(num % 2);
        }
    }
}


Q5. 정수 하나를 넘겨주면 그 정수번째의 피보나치 수열을 리턴해 주는 메소드

   1 1 2 3 5 8 13 21
class Q5{
public static void main(String[] args) {

        System.out.println(fibonacci(10));
    }

    public static int fibonacci(int num) {

        if (num <= 1)
            return num;
        return fibonacci(num - 1) + fibonacci(num - 2);
    }
}
  • 재귀함수를 점화식으로 보면 피보나치 수열에 있는 어느 한 숫자는 그 숫자보다 하나 앞에있는 수와 두개 앞에 있는 수를 합친 숫자이다.
class tQ5{
public static void main(String[]args){

        System.out.println(fibonacci(10));

    }
    public static int fibonacci(int num){

        if(num == 1 || num == 2) return 1;//이렇게도 가
        return fibonacci(num - 1) + fibonacci(num - 2);
    }
}    

class 선언

class: 만들고자 하는 객체의 상태와 행동을 정의해 놓은

클래스 구조

생성자

클래스로 부터 객체를 생성할때 초기 데이터 전달하는 역할 > 객체가 생성될 때 가장 처음 호출하는 메소

class Number{ //class라는 키워드로 Number이라는 클래스 정의 


    int num; //멤버 변수
    public void initNum(int n){      //initNum과 CurrentState는 멤버 메소드/ 메소드 이름은 의미있게 

        num = n;
    }
    public void printCurrentState(){

        System.out.println(num);
    }
}
class NumberMain{
    public static void main(String[]args){
        Number n1 = new Number(); //new 뒤는 클래스 명과 동일해야한다. > 1000번지라고 가정   
        n1.initNum(10);
        n1.printCurrentState(); //10
        Number n2 = new Number(); //n2라는 참조 변수에 주소값에 들어감/ 2000번지라고 가정
        n2.initNum(20); //n2로 2000번지 주소지를 찾아 Num에 20이 들어가고 n2는 사라진다.

        n2.printCurrentState();
        Number n3; //n3이라는 참조변수 선언 new 사용 안했으므로 변수만 선언 한것 
        n3 = n1; //1000번지라는 주소값이 n3에 들어감
        n3.printCurrentState(); //10 출력 
        n3 = n2; //2000번지 주소값 들어감                
        n3.printCurrentState(); //20 출력
        n3.initNum(30);    //n2의 initNum에 30 덮어쓰기 
        n2.printCurrentSatate(); //30출력 
        Number n4; //주소값을 저장할 수 있는 변수만 선언 = 참조 변수 (reference variable)
        Number n5 = new Number(); //new를 이용해 객체 생성 > 3000번지라고 가정 
}
}
  • new > 객체(object = instatnce) 생성하는 키워드

  • 객체를 생성할때 new 뒤는 클래스 명과 동일해야 한다.


멤버 변수 / 지역 변수

class Ex{
    boolean flag;
    public static void main(String[]args){
        boolean othflag;
        System.out.println(othflag); //1번
        System.out.println(flag);    //2번
  • 1번 othflag는 에러가 난다.

    • main메소드 안에서 선언한 지역변수로, 지역변수는 무조건 초기화 시켜야한다. > 아니면 에러
  • 2번 `flag 는 false가 출력된다

    • 메소드 밖에서 선언한 멤버 변수는 초기화 하지 않아도 출력되고, boolean의 기본값은 false다.

      • int의 기본값은 0
  • 지역변수와 멤버변수의 이름이 같으면 지역변수가 우선이다.


this 키워드

인스턴스 자기 자신을 가리키는 키워드 > 클래스를 기반으로 생성된 인스턴스를 가리키는 참조

  • 객체 자신의 대한 참조값을 가진다.(자기 자신을 가리킨다)

  • 메소드 내에서만 사용된다.

  • 객체 자신을 메소드에 전달하거나 리턴하기 위해 사용된다.

  • 매개 변수와 객체 자신이 가지고 있는 변수의 이름 같은 경우 이를 구분하기 위해 자신의 변수에 this를 사용한다.

    this.멤버 변수 : 매개 변수와 객체 자신이 가지고 있는 변수의 이름(지역 변수)가 같은경우 구분하기위해 this사용

    this(매개 변수) : 생성자 내에서 다른 생성자 호

  • static메소드에서는 사용할 수 없다.

class Ex{ //퀴즈 2번 참고 
    double radius;
    double area;
    double perimeter;
    public void initCircle(double radius){
        this.radius = radius; // 이렇게도 가능, 구분을 위한 this
        pi = 3.14;
        calPerimeter();
        calArea();
        printCS();
    }
}
  • 지역변수와 멤버 변수의 이름이 같으면 지역변수가 우선된다.

  • 초기화가 바로 되었으므로 저기서 calperimeter(); 등을 바로바로 초기화 메소드 안에 넣어서도 가능하다.


this() 메서드

자신이 속한 클래스에서 다른 생성자를 호출하는 경우 사용

  • this() 메서드는 반드시 생성자의 내부에서만 사용할 수 있다.

  • this() 메서드는 반드시 생성자의 첫 줄에 위치해야 한다.

public class Test{
     public static void main(String[] args) {
        Example example = new Example(5);
    }
}

class Example  {
    // 생성자1
    public Example() {
        System.out.println("기본 생성자 호출!");
    };
    // 생성자2
    public Example(int x) {
        this();
        System.out.println("두 번째 생성자 호출!");
    }
}

// 출력
// 기본 생성자 호출!
// 두 번째 생성자 호출!
  • Example 클래스는 두 개의 생성자를 가지고 있고, 생성자2는 this()메서드가 사용되고 있다.

  • 생성자 2를 사용하여 객체를 만들게 되면, 생성자2 안에 있는 this() 메서드가 실행되어 생성자1이 호출되고, 다음으로 두 번째 생성자가 호출된다.


퀴즈 - class 선언

Q1. 삼각형 클래스 만들기 (=멤버 변수) - 밑변, 높이, 넓이

멤버 메소드(= 인스턴스 메소드) - 삼각형 초기화하는 , 면적 구하는 , 현재 상태         출력하는(밑변, 높이, 넓이)

인스턴스 3개 만들기 - (밑변 10, 높이 5) / (밑변 4, 높이 2) / (밑변 20, 높이 10)

class Number { //클래스 이름은 대문자 / 멤버 변수 생성
    //밑에 애들은 메소드 밖에 있기 때문에 멤버 변수     
    int width;
    int length;
    int area;

    //void를 넣지않으면 에러, 반환값이 있는지 없는지 모르기 때문에 자바는 에러를 낸다. 
    public void initReset(int w, int l) { //삼각형 초기화 하는 메소드 (계산되는 건 x)
        //여기서 초기화 한다고 밑에서 초기화 한 명으로 사용은 x 처음에 멤버 변수 생성한 이름 그대로 사용

        //위에 멤버 변수와 다르게 메소드 안에 초기화해서 지역변수가 되는것 > 지역변수는 반드시 초기화 필
         width = w;
        length = l;

    }

    public void acreage() { //삼각형 면적 구하는 메소드 
        area = width * length / 2; //area는 계산해야하기 때문에 초기화 메소드에서는 x
    }

    public void state() { //삼각형 현재 상태 출력 메소드 
        System.out.print("밑변 : " + width + " 높이: " + length + " 넓이: " + area);
    }
}

class NumberMain {
//메인 메소드와 Number메소드 두개의 class가 생기는데 메인 메소드의 변수로 컴파일해야한다.
    public static void main(String[] args) {
        Number n1 = new Number();
//객체 생성 - Number의 주소를 저장하는 것이기 때문에 클래스Number 안에 값들을 사용하는 알고리즘 
        n1.initReset(10, 5);
        n1.acreage();
        n1.state();

        Number n2 = new Number();
        n1.initReset(4, 2);
        n1.acreage();
        n1.state();

        Number n3 = new Number();
        n3.initReset(20, 10);
        n3.acreage();
        n3.state();
    }
}
  •   initReset 에서 초기화 해서 w, l로 작성했는데 그러니 지역변수 선언하지 않았다고 오류 멤버 수에서 생성한 이름 사용해야한다. 

  • Main메소드의 이름으로 저장하지 않아 컴파일 안됐음

  • 멤버 메소드 안에서는 멤버 변수를 인식할 수 있다. > 메소드 밖에서 선언한 멤버 변수라서 Main메소드를 제외한 다른 메소드에서 다 사용 가능하다.

  • 지역변수는 초기화하지 않으면 에러난다.


Q2. 원 클래스 만들기 (= 멤버 변수) - 반지름(r)/면적(3.14 r r)/둘레 (2 3.14 2)/파이(3.14)

멤버 메소드 - 초기화하는 / 둘레 구하는 / 면적 구하는 / 상태를 출력하는(반지금, 둘레, 면적)

인스턴스 3개 만들기 - 반지름 5/ 반지름 10/ 반지름 30

class Circle { // 멤버 변수

    int radius;
    int area;
    int ference;
    double p = 3.14;
    int pie = (int) p;
//  int pie = (int)3.14; 이렇게 한번에 코드 작성하는게 더 가독성 좋음 

    public void initNum(int r) { //원 초기화 메소드
 // int r을 통해 지역변수를 이용하여 멤버변수에 값을 넣기 위함 - 기본으로 int r 에는 0이 들어있음 

        radius = r;
    //public void initNum(int radius)

    }

    public void cirFerence() { // 원 둘레 메소드

        ference = radius * 2 * pie;
    }

    public void cirArea() { // 원 면적 메소드

        area = ((radius * radius) * pie);
    }

    public void printCS() { // 원의 상태를 출력하는 메소드

        System.out.println("반지름 : " + radius);
        System.out.println("둘레 : " + ference);
        System.out.println("면적 : " + area);
    }
}

class CircleMain {
    public static void main(String[] args) {
        Circle c1 = new Circle(); //c1에 객체 생성한 주소지 대입 
        c1.initNum(5); //반지름 값 대입을 위한 문장 > int r을 5로 초기화 해주는 것 
        c1.cirFerence();
        c1.cirArea();
        c1.printCS();

        Circle c2 = new Circle(); //c2에 객체 생성한 주소지 대입 
        c2.initNum(10);
        c2.cirFerence();
        c2.cirArea();
        c2.printCS();

        Circle c3 = new Circle(); //c3에 객체 생성한 주소지 대입 
        c3.initNum(30);
        c3.cirFerence();
        c3.cirArea();
        c3.printCS();
    }
}
  • c1은 이미 객체 생성을 했는데 그 위로 c1에 객체 생성하면 그 전에 생성했던 객체가 지워지지않아 메모리 누수가 발생한다.
    • 그래서 c2, c3생성해서 새로운 곳에 새로운 객체의 주소값을 넣는것이다.

  • 만약 소수점으로 결과값을 반환받고 싶다면 처음 멤버변수할 때 int로 선언이 아닌 double로 선언하면 된다.

Newest Questions - Stack Overflow - 개발자들의 지식인 공간

0개의 댓글