Java 6일차 : 클래스

클래스

  • 클래스는 설계도면 같은것
  • 필요한 요소들을 넣어서 설계를 하고 그 설계대로 집을 짓는다

  • 마찬가지로 클래스구조를 설계해서 만든다음, New로 인스턴스 생성을 하면 비로소 메모리에 클래스 객체가 생성되며, 이것이 집의 주소와 같은 개념이라고 보면된다.

공부해야할것

  1. 멤버 변수, 멤버 메소드 구현하는 방법
  2. 접근 지정자
  3. 클래스 객체를 생성 후 메소드 호출하는 방법
  4. 오버라이드 메소드에 대한 이해
  5. 생성자
  6. 상속
  7. 다형성
package test.day0410;

public class ObjectEx2 {
  //멤버 변수 선언하는 위치 - 이안에서 생성될 오브젝트에서 공통적으로 사용할 수 있는 변수
  //형식 : 접근지정자 [final, static] 데이타타입 변수
  //접근지정자(4개) : public, protected, private, 생략 
  //public : 모든 패키지에서 접근 가능
  //private : 타 패키지 뿐 아니라 같은 패키지에서도 접근 불가능. 현재 클래스 멤버만 접근 가능
  //protected : 패키지가 다를 경우 상속관계의 클래스만 접근을 허용하고 싶을 때
  //생략시 : 다른 패키지에서 무조건 접근 불가 
  private int x1 = 100;
  private String msg="happy";
  public void writeMember() {
    System.out.println(x1); //멤버메소드에서는 멤버변수 바로 접근 가능 
    System.out.println(this.x1); //this라는 인스턴스 변수가 기본적으로 존재(위처럼 생략 가능) 
    System.out.println(msg);
    System.out.println(this.msg);
  }
  //멤버 메소드라 하더라도 static메소드는 this를 갖고있지 않다.
  public static void main(String []arg) {
    // System.out.println(x1); //메인에서는 같은 클래스라 하더라도 new로 생성 후 호출해줘야함 
    //현재 클래스에 대한 객체 생성
    ObjectEx2 ex = new ObjectEx2();
    //이제 멤버변수를 호출할 수 있다.
    System.out.println(ex.x1 + 1);
    System.out.println(ex.msg + " main method");
    //멤버 메소드 호출
    ex.writeMember();
  }
}
package test.day0410;

import test.day0409.Apple2;

public class ObjectEx3 {

  public static void main(String[] args) {
    // TODO Auto-generated method stub
    //같은 패키지의 apple멤버 메소드를 호출하자
    Apple apple = new Apple();
    apple.testPublic();
    apple.testProtected();
    apple.testDefault();
    //apple.testPrivate(); -> 오류 
    //같은 패키지내에서는 private을 제외한 접근지정자는 모두 접근가능
    Apple2 apple2 = new Apple2();
    apple2.testPublic();
    //다른 패키지에 있는 클래스는 퍼블릭 메소드만 접근 가능 
  }
}
package test.day0410;

class Orange{
  int n = 10;
  public void test1() {
    int n = 20;
    //같은 이름의 지역변수가 없다면 멤버변수가 출력되지만
    //같은 이름의 지역변수가 있다면 지역변수가 우선으로 출력
    System.out.println(n);
    //만약 멤버변수를 호출해주고 싶다면 반드시 this.n으로 사용!
    System.out.println(this.n);
  }
  public void test2(int n) {
    System.out.println(n);
    System.out.println(this.n);
  }
}
class Kiwi{
  //static 멤버변수는 외부에서 클래스명. 상수명 으로 접근 가능 
  public static final String MSG = "Happy Day!!!";
  public static final double PI = 3.141592;
}

public class ObjectEx4 {

  public static void main(String []arg) {
    Orange or = new Orange();
    or.test1();
    or.test2(5);
    //static 변수나 메소드는 모든 객체에서 공동으로 사용할 목적으로 만들어짐 
    //new로 굳이 객체생성 불필요함 
    System.out.println(Kiwi.MSG + Kiwi.PI);
  }
}
package test.day0410;

class Berry{

  private static String msg = "Happy";
  private String addr = "Seoul";

  public void test1() {
    System.out.println(msg);
    System.out.println(addr);
  }

  public static void test2() {
    System.out.println(msg);
    //System.out.println(addr); //static메소드안에 non-static 변수를 사용x
    //굳이 non-static 변수를 쓰고 싶으면 항상 아래처럼 호출 후 사용해줄
    Berry br = new Berry();
    System.out.println(br.addr);
  }
  public void hello1() {
    test1();
    test2();
  }
  public static void hello2() {
    //test1(); //static 메소드 안에 non-static 메소드를 사용x
    test2();
  }
}

public class ObjectStaticEx5 {

  public static void main(String[] args) {

  }
}

기본적으로 class는 인스턴스가 생성되기 전까지는 단순히 설계도에 불과한 것처럼 보인다.

다만, 클래스 내의 static 변수나 static 메서드는 이미 그 선언 자체로 사용이 가능하다.

그러니까 여러개의 집을 짓기 전에 설계도를 작성하지만, 어쨋든 지어질 집이라면 단지 내 주차장은 어차피 만들어야하니, 귀찮게 집을 지을때마다 주차장을 만들지 말고 걍 미리 주차장은 만들어놓는다는 개념

같은 원리로 공동의 어떤 행동을 할 때, 공동의 것이 아닌 변수를 가져오는것은 불가능(왜냐하면 설계도가 존재한다는 것 자체로 101호가 존재한다고 볼 순 없기 때문임)

그래서 non-static 변수를 가져오기 전엔 반드시 집(인스턴스)을 적어도 하나는 짓고 가져와야함

같은 원리로 공동의 어떤 행동을 할 때, 공동의 것이 아닌 행동을 가져오는것은 불가능

마찬가지로 그냥 설계도만 있는 상태이기 때문에 101호 청소하기 같은 non-static 메소드를 공동계단 청소하기같은 static 메소드에 집어넣는것은 안됨 (101호가 없는데 어떻게 청소를해?)

실습문제

Student 라는 클래스를 설계해보자

멤버변수(모두 private) : 이름 name / 주소 addr / 반 room - static / 점수 score

멤버메소드 : setName / setAddr / setRoom - static / setScore / writeStudent - 전체 데이타 출력하는 메소드

package test.day0410;

class Student {
  //멤버 변수 선언 
  private String name;
  private String addr;
  static int room;
  private int score;
  //setter멤버메소드 
  public void setName(String name) {
    //전달받은 인자 name을 멤버변수에 넣기 
    this.name = name; 
  }
  public void setAddr(String addr) {
    this.addr = addr;
  }
  public static void setRoom(int room) {
    Student.room = room;
  }
  public void setScore(int score) {
    this.score = score;
  }
  public void writeStudent() {
    //같은 멤버끼리는 this나 Student 생략가능 
    System.out.println("name: " + name);
    System.out.println("addr: " + addr);
    System.out.println("room: " + room);
    System.out.println("score: " + score);
  }
  public void setStudent(String name, String addr, int score) {
    setName(name);
    setAddr(addr);
    setScore(score);
  }
}

public class StudentEx6 {

  public static void main(String[] args) {
    // TODO Auto-generated method stub
    Student alice = new Student();
    Student bob = new Student();
    alice.setName("alice");
    alice.setAddr("Seoul");
    alice.setRoom(3); //어차피 이건 공유되는거니까 그냥 Student.setRoom으로 줘도 된다. 
    alice.setScore(90);
    alice.writeStudent();
    System.out.println(); 
    bob.writeStudent(); //room 변수는 이미 들어가 있다.
    System.out.println(); 

    bob.setName("bob");
    bob.setAddr("Busan");
    bob.setScore(13); 
    bob.writeStudent();
    System.out.println(); 

    alice.setStudent("chris", "Seattle", 88);
    alice.writeStudent();
  }
}

의문점

static 메서드에서, 해당 클래스의 인스턴스 변수에 접근하기 위해 생성된 오브젝트 obj가 있다고 하자. 이 때 메인메서드에서 이 오브젝트에 접근할 수 있는가? 예를들어 obj.var1 값을 메인메서드에서 호출할 수 있는가?

=> 된다. 만약 그 static메서드가 obj를 반환하도록 되어있다면.

그럼 메인메서드에서 그 static메서드를 호출하면, obj를 얻을 수 있으므로 자유롭게 변수에 접근 가능하다. 근데.. 음….. 변경도 가능한가? call-by-value인가?

=> call-by-value다. 변경은 안된다. 변경값을 저장하고 싶다면 애초에 메인메서드에서 obj를 다른 인스턴스에 저장해서 사용해야 변경이 유효하다.

Return 타입

package test.day0410;

class Banana{

  private String name = "Lisa";
  private int age = 17;
  public int myAge() {
    return age;
  }
  public String myName() {
    return name;
  }
  public Banana getBanana() {
    return this; //현재값으로 반환(나이,이름)
  }
  public static Banana getMyData() {
    Banana b = new Banana();
    b.name = "Rose";
    b.age = 20;
    return b;
  }
}

public class ReturnTypeEx7 {

  public static void main(String[] args) {
    // TODO Auto-generated method stub
    Banana bn = new Banana();
    System.out.println(bn.myAge() + bn.myName());
    System.out.println(bn.getBanana().myAge()); //메서드 직접 호출 
    Banana b2 = Banana.getMyData(); //static 메서드 호출
    //위에서 getMyData는 banana 클래스의 오브젝트를 반환하므로 b2에 저장될 수 있다
    System.out.println(b2.myName());
  }
}
package test.day0410;

class MyMath{

  public static double sum(double a, double b) {
    return a+b;
  }
  //overloading method(중복 메서드) - 메서드 명은 같으나 인자는 서로 달라야함 
  public static double sum(double a, double b, double c) {
    return a+b+c;
  }
  //...배열타입 
  public static double sum(double...d) {
    double s = 0.0;
    for(int i = 0 ; i<d.length ; i++) {
      s += d[i];
    }
    return s;
  }
}

public class ReturnTypeEx8 {

  public static void main(String[] args) {
    // TODO Auto-generated method stub
    double d1=MyMath.sum(3.2,  5.1);
    System.out.println(d1);
    System.out.println(MyMath.sum(1.1, 2.2, 3.3)); //오버로딩 
    System.out.println(MyMath.sum(1.1,2.2,3.3,4.4,5.5));
  }
}

Variable Arguments

  • 같은 타입으로 여러개의 값을 인자로 받을 경우, 여러개의 오버로딩 메서드를 만들어야 하는 경우에 유용하게 쓸 수 있는 기능이다 (jdk5.0에서 추가)
package test.day0410;

public class VaragesEx9 {
  //variable argument ...
  public static void writeString(String...str) {
    System.out.println(str.length + "개의 문자열 받음.");
    for(int i = 0 ; i < str.length ; i++) {
      System.out.print(str[i]);
    }
  }
  public static void main(String []arg) {
    writeString("안녕하세요~!!", "ㅎㅇㅎㅇ","ㅎㅎ");
  }
}

실습문제

다음과 같은 클래스를 구현하시오

클래스명: Pay

​ 멤버변수 : gibon : 기본급, sudang : 수당, tax : 세금

​ =>모든 멤버변수는 private 으로 주고 setter & getter 메소드를 구현한다

​ =>메소드 추가 calcTax : 기본급의 3프로를 tax 에 지정한다

클래스명 : Sawon

​ 멤버변수 : name : 사원명, mypay : 급여에 대한 정보

​ 멤버 메소드 :

​ initPay :기본급과 수당을 전달받아서 mypay 에 전달,

​ writeSawon : 사원명,기본급,수당,세금 출력하는 메소드

package test.day0410;

class Pay{
  private int gibon, sudang, tax;

  public int getGibon() {
    return gibon;
  }

  public void setGibon(int gibon) {
    this.gibon = gibon;
  }

  public int getSudang() {
    return sudang;
  }

  public void setSudang(int sudang) {
    this.sudang = sudang;
  }

  public int getTax() {
    return tax;
  }

  public void setTax(int tax) {
    this.tax = tax;
  }
  public void calcTax() {
    this.tax = (int)(gibon*0.03);
  }
}

class Sawon{
  String name = "홍길동";
  Pay myPay = new Pay();
  public void initPay(int gibon, int sudang) {
    myPay.setGibon(gibon);
    myPay.setSudang(sudang);
  }
  public void writeSawon() {
    System.out.println(name);
    System.out.println(myPay.getGibon());
    System.out.println(myPay.getSudang());
    System.out.println(myPay.getTax());
  }
}

public class ClassTestEx11 {

  public static void main(String[] args) {
    // TODO Auto-generated method stub
    Sawon sa=new Sawon();
    sa.initPay(1260000,350000);
    sa.myPay.calcTax();
    sa.writeSawon();
  }
}

Categories:

Updated:

Comments