본문 바로가기
Web & Mobile/JAVA

Lecture 23 - Java(4) 변수와 메서드, 생성자

by Bennyziio 2019. 4. 19.
반응형

자료형
    기본 자료형
        변수 공간안에 데이터 저장
        
* 오라클이 제공하는 내용을 사용
        Boolean
        char
        byte
, short, int, long
        float
, double

자바
- 프로그램 기법(객체의 기능정의) - 패턴(교수님들이 제안)

자바 디자인 패턴
= UML(Unified Modeling Language) 모델 생성 - UML 다이어그램
- 아키텍쳐가 짠다

    디자인 패턴
=> UML 다이어그램(설계도)
참조 자료형
-- OOP(Object Oriented Programming)
    변수 공간안에 데이터에 대한
참조(메모리 주소)가 저장

    사용자 정의
- 문법
    
* 사용자가 만들어서 사용하는 복합자료형(여러 자료형의 묶음)
        속성
- 멤버변수, 필드
        기능
- 메서드(함수)

    
사물                                                         (객체)변수
    사물
-> 공통성 -> 객체 -> 클래스 -> 구체화 -> (객체)변수
    
사물                                                         (객체)변수

    
공통성(Abstraction) - 추상(추출)
    Abstraciton
- 논문 초록(요약)

    
<->

    
API(라이브러리) - 사용
        내장객체
        외부객체

변수와 메서드
1. 인스턴스변수
2. 클래스변수
3. 지역변수

VariableEx02

class Variable {
    // 멤버 변수
    //      인스턴트 변수
    //      클래스 변수
    // 메서드
    //      지역 변수
    void doMethod() {
        int lv1 = 10;
        System.out.println("lv1 : " + lv1);
    }
}

public class VariableEx02 {
    public static void main(String[] args) 
    {
        Variable v = new Variable();
        v.doMethod();
    }
}

class Variable {
    // 멤버 변수
    //      인스턴트 변수
    //      클래스 변수
    // 메서드
    //      지역 변수
    void doMethod() {
        int lv1 = 10;
        {
            int lv2 = 20;
        }
        System.out.println("lv1 : " + lv1);
        System.out.println("lv2 : " + lv2);
    }
}

public class VariableEx02 {
    public static void main(String[] args) 
    {
        Variable v = new Variable();
        v.doMethod();
    }
}

지역변수는 해당 메서드 안에서만 사용 가능하므로 에러남

class Variable {
    // 멤버 변수
    //      인스턴트 변수
    //      클래스 변수
    // 메서드
    //      지역 변수
    void doMethod() {
        int lv1 = 10;
        {
            int lv2 = 20;
            System.out.println("lv2 : " + lv2);
        }
        System.out.println("lv1 : " + lv1);
    }
}

public class VariableEx02 {
    public static void main(String[] args) 
    {
        Variable v = new Variable();
        v.doMethod();
    }
}

위와 같이 지역변수가 선언된 메서드 안에서 출력 명령을 하여 정상 출력 됨

class Variable {
    // 멤버 변수
    //      인스턴트 변수
    //      클래스 변수

    int iv = 10;            // 인스턴스
    static int sv = 20;     // 클래스

    // 메서드
    //      지역 변수
    void doMethod() {
        int lv1 = 10;
        {
            int lv2 = 20;
            System.out.println("lv2 : " + lv2);
        }
        System.out.println("lv1 : " + lv1);
    }
}

public class VariableEx02 {
    public static void main(String[] args) 
    {
        Variable v = new Variable();
        v.doMethod();
        
        System.out.println("iv : " + v.iv);
        System.out.println("sv : " + v.sv);

        //System.out.println("iv : " + Variable.iv);
        // 클래스 멤버 변수는 클래스 이름을 통해서 접근
        System.out.println("sv : " + Variable.sv);
    }
}

인스턴스 변수는 Variable 접근시 에러가 남(객체를 인스턴스화 하여 메모리에 저장 시키기 때문)

클래스 변수는 클래스 이름을 통해서 접근하므로 정상 출력 됨(프로그램이 시작되면 메모리에 변수가 저장이 되므로)

class Variable {
    // 멤버 변수
    //      인스턴트 변수
    //      클래스 변수

    int iv = 10;            // 인스턴스
    static int sv = 20;     // 클래스

    // 메서드
    //      지역 변수
    void doMethod() {
        int lv1 = 10;
        {
            int lv2 = 20;
            System.out.println("lv2 : " + lv2);
        }
        System.out.println("lv1 : " + lv1);
    }
}

public class VariableEx02 {
    public static void main(String[] args) 
    {
        //Variable v = new Variable();
        //v.doMethod();
        
        //System.out.println("iv : " + v.iv);
        //System.out.println("sv : " + v.sv);

        //System.out.println("iv : " + Variable.iv);
        // 클래스 멤버 변수는 클래스 이름을 통해서 접근
        System.out.println("sv : " + Variable.sv);
    }
}

전역 변수의 성격을 갖게 되므로 정상 출력 됨

StaticMain

class StaticEx01 {
    static int sv1 = 10;
}

class StaticEx02 {
    static int sv2 = 20;
}

public class StaticMain {
    public static void main(String[] args)
    {
        System.out.println("sv1 : " + StaticEx01.sv1);
        System.out.println("sv2 : " + StaticEx02.sv2);
    }
}

class StaticEx01 {
    static int sv1 = 10;
    static int sv = 30;
}

class StaticEx02 {
    static int sv2 = 20;
    static int sv = 30;
}

public class StaticMain {
    public static void main(String[] args)
    {
        System.out.println("sv1 : " + StaticEx01.sv1);
        System.out.println("sv2 : " + StaticEx02.sv2);

        System.out.println("StaticEx01.sv : " + StaticEx01.sv);
        System.out.println("StaticEx02.sv : " + StaticEx02.sv);
    }
}

static int sv라는 같은 변수가 다른 클래스로 분류되어 있기 때문에 에러없이 동작한다.(클래스 별 독립성)

// static - 공유 / 클래스간의 통신

class StaticEx01 {
    static int sv1 = 10;
    static int sv = 30;

    void doPrint() {
        System.out.println("StaticEx01.sv : " 
        + StaticEx01.sv);
    }
}

class StaticEx02 {
    static int sv2 = 20;
    static int sv = 30;

    void doPrint() {
        System.out.println("StaticEx01.sv : " 
        + StaticEx01.sv);
    }
}

public class StaticMain {
    public static void main(String[] args)
    {
        System.out.println("sv1 : " + StaticEx01.sv1);
        System.out.println("sv2 : " + StaticEx02.sv2);

        System.out.println("StaticEx01.sv : " + StaticEx01.sv);
        System.out.println("StaticEx02.sv : " + StaticEx02.sv);

        StaticEx01 s1 = new StaticEx01();
        StaticEx02 s2 = new StaticEx02();

        s1.doPrint();
        s2.doPrint();

        s1.sv = 60;

        s1.doPrint();
        s2.doPrint();
    }
}

CardTest

class Card {
    String kind;
    int number;
    static int width = 100;
    static int height = 250;
}

class CardTest {
    public static void main(String[] args)
    {
        System.out.println("card.width = " + Card.width);
        System.out.println("card.height = " + Card.height);

        Card c1 = new Card();
        c1.kind = "Heart";
        c1.number = 7;

        Card c2 = new Card();
        c2.kind = "Spade";
        c2.number = 4;

        System.out.println("c1은" + c1.kind + ", " + c1.number
                    + "이며, 크기는 (" + c1.width + ", " + c1.height + ")" );
        System.out.println("c2는" + c2.kind + ", " + c2.number
                    + "이며, 크기는 (" + c2.width + ", " + c2.height + ")" );
        System.out.println("c1의 width와 height를 각각 50, 80으로 변경합니다.");
        c1.width = 50;
        c1.height = 80;
        
        System.out.println("c1은" + c1.kind + ", " + c1.number
                    + "이며, 크기는 (" + c1.width + ", " + c1.height + ")" );
        System.out.println("c2는" + c2.kind + ", " + c2.number
                    + "이며, 크기는 (" + c2.width + ", " + c2.height + ")" );

    }
}

인스턴스벼수는 인스턴스가 생성될 때 마다 생성되므로 인스턴스마다 각기 다른 값을 유지할 수 있지만, 클래스 변수는 모든 인스턴스가 하나의 저장공간을 공유하므로, 항상 공통된 값을 갖는다.

메서드
메서드를 사용하는 이유
1. 높은 재사용성
2.중복된 코드의 제거
3. 프로그램의 구조화

클래스 메서드(static메서드)와 인스턴스 메서드

class Variable {
    //int iv = 10;

    static void doTest1() {
        // static - static만 접근 가능
        System.out.println("doTest1()");
    }

    void doTest2() {
        System.out.println("doTest2()");
    }
}

public class VariableEx03 {
    public static void main(String[] args)
    {
        Variable v = new Variable();
        v.doTest2();

        Variable.doTest1();
    }
}

class Variable {
    int iv = 10;

    static void doTest1() {
        // static - static만 접근 가능
        System.out.println("doTest1() : " + iv);
    }

    void doTest2() {
        System.out.println("doTest2() : " + iv);
    }
}

public class VariableEx03 {
    public static void main(String[] args)
    {
        Variable v = new Variable();
        v.doTest2();

        Variable.doTest1();
    }
}

스태틱은 스태틱만 접근이 가능하다

class Variable {
    int iv = 10;

    static void doTest1() {
        // static - static만 접근 가능
        //System.out.println("doTest1() : " + iv);
    }

    void doTest2() {
        System.out.println("doTest2() : " + iv);
    }
}

public class VariableEx03 {
    public static void main(String[] args)
    {
        Variable v = new Variable();
        v.doTest2();

        Variable.doTest1();
    }
}

class Variable {
    int iv = 10;
    static int sv = 20;
    static void doTest1() {
        // static - static만 접근 가능
        //System.out.println("doTest1() : " + iv);
        System.out.println("doTest1() : " + sv);
    }

    void doTest2() {
        System.out.println("doTest2() : " + iv);
        System.out.println("doTest3() : " + sv);
    }
}

public class VariableEx03 {
    public static void main(String[] args)
    {
        Variable v = new Variable();
        v.doTest2();

        Variable.doTest1();
    }
}

static으로 선언하면 다 사용할 수 있다.

1. 클래스를 설계할 때 멤버변수 중 모든 인스턴스에 곹옹으로 사용하는 것에 static을 붙인다.
- 생성된 각 인스턴스는 서로 독립적이기 때문에 각 인스턴스의 변수 (iv)는 서로 다른 값을 유지한다. 그러나 모든 인스턴스에서 같은 값이 유지되어야 하는 변수는 static을 붙여서 클래스변수로 정의해야한다.
2. 클래스 변수(static변수)는 인스턴스를 생성하지 않아도 사용할 수 있다.
- static이 붙은 변수(클래스변수)는 클래스가 메모리에 올라갈 때 이미 자동적으로 생성되기 때문이다.
3. 클래스 메서드(static메서드)는 인스턴스 변수를 사용할 수 없다.
- 인스턴스변수는 인스턴스가 반드시 존재해야만 사용할 수 있는데, 클래스메서드(static이 붙은 메서드)는 인스턴스 생성 없이 호출가능하므로 클래스 메서드가 호출되었을 때 인스턴스가 존재하지 않을 수도 있다. 그래서 클래스 메서드에서 인스턴스변수의 사용을 금지한다. 
반면에 인스턴스변수나 인스턴스메서드에서는 static이 붙은 멤버들을 사용하는 것이 언제나 가능하다. 인스턴스 변수가 존재한다는 것은 static변수가 이미 메모리에 존재한다는 것을 의미하기 때문이다.
4. 메서드 내에서 인스턴스 변수를 사용하지 않는다면, static을 붙이는 것을 고려한다.
- 메서드의 작업내용 중에서 인스턴스변수를 필요로 한다면, static을 붙일 수 없다. 반대로 인스턴스변수를 필요로 하지 않는다면 static을 붙이자. 메서드 호출시간이 짧아지므로 성능이 향상된다. static을 안 붙인 메서드(인스턴스메서드)는 실행 시 호출되어야할 메서드를 찾는 과정이 추가적으로 필요하기 때문에 시간이 더 걸린다.

- 클래스의 멤버변수 중 모든 인스턴스에 공통된 값을 유지해야하는 것이 있는지 살펴보고 있으면, static을 붙여준다.
- 작성한 메서드 중에서 인스턴스 변수나 인스턴스 메서드를 사용하지 않는 메서드에 static을 붙일 것을 고려한다.

static의 단점
1. static이 많아지면 저장공간을 많이 쓰게되고 그로 인해 용량이 커진다.
2. 협업시 서로 충돌이 일어날 경우가 생긴다.

오버로딩의 조건
1. 메서드 이름이 같아야 한다.
2. 매개변수의 개수 또는 타입이 달라야 한다.

오버로딩의 장점
1. 메서드의 이름만 보고도 '이 메서드들은 이름이 같으니, 같은 기능을 하겠구나.'라고 쉽게 예측 가능
2. 메서드의 이름을 절약할 수 있다.

OverloadingTest

class MyMath3 {
    int add(int a, int b) {
        System.out.println("int add(int a, int b) - ");
        return a+b;
    }

    long add(int a, long b) {
        System.out.println("int add(int a, long b) - ");
        return a+b;
    }

    long add(long a, int b) {
        System.out.println("long add(long a, int b) - ");
        return a+b;
    }

    long add(long a, long b) {
        System.out.println("long add(long a, long b) - ");
        return a+b;
    }

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

class OverloadingTest {
    public static void main(String[] args)
    {
        MyMath3 mm = new MyMath3();
        System.out.println("mm.add(3, 3) 결과 : " + mm.add(3,3));
        System.out.println("mm.add(3L, 3) 결과 : " + mm.add(3L,3));
        System.out.println("mm.add(3, 3L) 결과 : " + mm.add(3,3L));
        System.out.println("mm.add(3L, 3L) 결과 : " + mm.add(3L,3L));

        int[] a = {100, 200, 300};
        System.out.println("mm.add(a) 결과 : " + mm.add(a));
    }
}

가변인자(varargs)와 오버로딩 - Variable Arguments

class Varargs {
    //void doTest(String name1) {}
    //void doTest(String name1, String name2) {}
    
    // ... 원하는 갯수만 자료 입력
    void doTest(String ... names) {
        // names - 배열 선언이됨
        System.out.println(names.length);
    }
}

public class VarargsMain {
    public static void main(String[] args)
    {
        Varargs v = new Varargs();
        v.doTest("1");
        v.doTest("1", "2");
        v.doTest("1", "2", "3");
    }
}

class Varargs {
    //void doTest(String name1) {}
    //void doTest(String name1, String name2) {}
    
    // ... 원하는 갯수만 자료 입력
    void doTest(String ... names) {
        // names - 배열 선언이됨
        System.out.println(names.length);

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

public class VarargsMain {
    public static void main(String[] args)
    {
        Varargs v = new Varargs();
        v.doTest("1");
        v.doTest("1", "2");
        v.doTest("1", "2", "3");
    }
}

length 나오고 content나오고 순으로 출력됨

Gugudan이라는 클래스 내에 doGugudan이라는 메서드를 만들고 
doGugudan(1) - 1단
doGugudan(1, 2) - 1단, 2단
doGugudan(1, 2, 3) - 1단, 2단, 3단

내가 한거

class Gugudan {
    void doGugudan(Number ... names) {
        for(int i=1; i<(names.length+1); i++) {
            for(int j=1; j<10; j++) {
                System.out.printf("%d x %d = %d%n", i, j, i*j);
            }
        }
    }
}

public class GugudanMain {
    public static void main(String[] args) {
        Gugudan v = new Gugudan();
        v.doGugudan(1);
        v.doGugudan(1, 2);
        v.doGugudan(1, 2, 3);
    }
}

강사님이 한거

class Gugudan {
    void doGugudan(int ... dans) {
        for(int dan : dans) {
            for(int j=1; j<=5; j++) {
                System.out.printf("%2d x %2d = %3d ", dan, j, (dan*j));
            }
            System.out.print("\n");
        }
    }
}

public class Util {
    public static void main(String[] args) {
        Gugudan v = new Gugudan();
        v.doGugudan(1);
        v.doGugudan(1, 2);
        v.doGugudan(1, 2, 3);
    }
}

VarArgsEx

class VarArgsEx {
    public static void main(String[] args)
    {
        String[] strArr = {"100", "200", "300"};

        System.out.println(concatenate("", "100", "200", "300"));
        System.out.println(concatenate("-", strArr));
        System.out.println(concatenate(",", new String[]{"1", "2", "3"}));
        System.out.println("["+concatenate(",", new String[0])+"]");
        System.out.println("["+concatenate(",")+"]");
    }

    static String concatenate(String delim, String... args) {
        String result = "";

        for(String str : args) {
            result += str + delim;
        }

        return result;
    }
}

생성자(Constuctor)
생성자는 인스턴스가 생성될 때 호출되는 '인스턴스 초기화 메서드'이다. 따라서 인스턴스 변수의 초기화 작업에 주로 사용되며, 인스턴스 생성 시에 실행되어야 할 작업을 위해서도 사용된다.
1. 생성자의 이름은 클래스의 이름과 같아야 한다.
2. 생성자는 리턴값이 없다.

ConstructorEx01

class Constructor {
    // 생성자 선언
    Constructor() {
        System.out.println("Constructor() 호출");
    }
}

public class ConstructorEx01 {
    public static void main(String[] args)
    {
        // 생성자 호출
        // new 생성자
        Constructor c = new Constructor();
    }
}

class Constructor {
    // 생성자 선언

    // 생성자 오버로딩
    Constructor() {
        System.out.println("Constructor() 호출");
    }

    Constructor(int x) {
        System.out.println("Constructor(x) 호출");
    }
}

public class ConstructorEx01 {
    public static void main(String[] args)
    {
        // 생성자 호출
        // new 생성자
        Constructor c1 = new Constructor();

        // 1. 생성자는 클래스를 생성(객체 변수화 시키는 방법)
        // 2. 멤버변수의 초기화
        Constructor c2 = new Constructor(10);
    }
}

ConstructorEx02 - 멤버변수의 초기화

class Constructor {
    String data1;
    int data2;

    Constructor() {
        // 멤버변수의 초기화
        data1 = "홍길동";
        data2 = 30;
    }
}

public class ConstructorEx02 {
    public static void main(String[] args)
    {
        Constructor c = new Constructor();
        System.out.println(c.data1);
        System.out.println(c.data2);
    }
}

class Constructor {
    String data1;
    int data2;

    Constructor() {
        // 멤버변수의 초기화
        data1 = "홍길동";
        data2 = 30;
    }

    Constructor(String name, int age) {
        data1 = name;
        data2 = age;
    }
}

public class ConstructorEx02 {
    public static void main(String[] args)
    {
        Constructor c = new Constructor();
        System.out.println(c.data1);
        System.out.println(c.data2);

        Constructor c1 = new Constructor("박문수", 24);
        Constructor c2 = new Constructor("성춘향", 21);
        System.out.println(c1.data1);
        System.out.println(c2.data1);
    }
}

CarTest - 매개변수가 있는 생성자
생성자도 메서드처럼 매개변수를 선언하여 호출 시 값을 넘겨받아서 인스턴스의 초기화작업에 사용할 수 있다. 인스턴스마다 각기 다른 값으로 초기화되어야하는 경우가 많기 때문에 매개변수를 사용한 초기화는 매우 유용하다.

class Car {
    String color;
    String gearType;
    int door;

    Car() {}
    Car(String c, String g, int d) {
        color = c;
        gearType = g;
        door = d;
    }
}

public class CarTest {
    public static void main(String[] args)
    {
        Car c1 = new Car();
        c1.color = "white";
        c1.gearType = "auto";
        c1.door = 4;

        Car c2 = new Car("white", "auto", 4);
        System.out.println("c1의 color=" + c1.color + ", gearType="
                            + c1.gearType+ ", door="+c1.door);
        System.out.println("c2의 color=" + c2.color + ", gearType="
                            + c2.gearType+ ", door="+c2.door);
    }
}

생성자에서 다른 생성자 호출하기 - this(), this

class Constructor {
    String data1;
    int data2;

    Constructor() {
        
    }

    Constructor(String name, int age) {
        
    }
}

public class ConstructorEx03 {
    public static void main(String[] args)
    {
        Constructor c = new Constructor();
        System.out.println("c : " + c);
    }
}

class Constructor {
    String data1;
    int data2;

    Constructor() {
        System.out.println("this : " + this);
    }

    Constructor(String name, int age) {
        
    }
}

public class ConstructorEx03 {
    public static void main(String[] args)
    {
        Constructor c = new Constructor();
        System.out.println("c : " + c);
    }
}

class Constructor {
    String data1 = "홍길동";
    int data2 = 40;

    Constructor() {
        // 메모리의 시작주소
        System.out.println("this : " + this);

        System.out.println("data1 : " + data1);
        System.out.println("data1 : " + this.data1);
    }

    Constructor(String name, int age) {
        
    }
}

public class ConstructorEx03 {
    public static void main(String[] args)
    {
        Constructor c = new Constructor();
        System.out.println("c : " + c);
    }
}

class Constructor {
    String data1 = "홍길동";
    int data2 = 40;

    Constructor() {
        // 메모리의 시작주소
        System.out.println("this : " + this);

        System.out.println("data1 : " + data1);
        System.out.println("data1 : " + this.data1);
    }

    //Constructor(String name, int age) {
    Constructor(String data1, int data2) {
        //data1 = name;
        this.data1 = data1;
        this.data2 = data2;
    }
}

public class ConstructorEx03 {
    public static void main(String[] args)
    {
        Constructor c = new Constructor();
        System.out.println("c : " + c);
    }
}

외부의 data1과 내부의 data1을 일치시킬때 this를 사용하여 호출한다

class Constructor {
    String data1 = "홍길동";
    int data2 = 40;

    Constructor() {
        // 메모리의 시작주소
        System.out.println("this : " + this);

        System.out.println("data1 : " + data1);
        System.out.println("data1 : " + this.data1);
    }

    //Constructor(String name, int age) {
    Constructor(String data1, int data2) {
        //data1 = name;

        // this : 멤버변수 / 멤버 메서드 참조
        this.data1 = data1;
        this.data2 = data2;

        this.doPrint();
    }

    void doPrint() {
        System.out.println("data1 : " + this.data1);
        System.out.println("data2 : " + this.data2);
    }
}

public class ConstructorEx03 {
    public static void main(String[] args)
    {
        Constructor c = new Constructor();
        System.out.println("c : " + c);
        
        Constructor c1 = new Constructor("박문수", 20);
    }
}

 

반응형

댓글