써먹는 웹개발

[Java] 11강 레퍼런스와 static편 학습 내용 보내드립니다. 본문

Study/Java & Python

[Java] 11강 레퍼런스와 static편 학습 내용 보내드립니다.

kmhan 2021. 2. 25. 16:14


728x90
반응형

11 레퍼런스와 static
일반 변수와 객체를 가리키는 변수

 

// 일반 변수
int score = 88;


// 객체를 가리키는 변수
Cat cat1 = new Cat();

 

 

 

 

1. 레퍼런스 변수

 - 레퍼런스 변수는 객체를 가리킨다.

 

 

// 객체 생성 후, 그 객체의 주소를 marine1 변수에 저장, 그 객체를 Marine 타입으로 해석.

Marine marine1 = new Marine("레이너", 80);

 

// marine1 주소의 객체에 접근하여, stimpack() 동작을 실행

marine1.stimpack();

 

2. 기본형 변수

 - 값을 직접 저장하는 변수

 

 

 

 - 자료형 8가지

 

 

 

3. 기본형 변수와의 차이

 - 표기 방식 : 레퍼런스 형은 대문자로 시작하는 반면에 원시형 변수는 소문자로 시작한다.

 - 저장 방식 : 레퍼런스 변수는 객체의 주소를 저장함으로써 간접적으로 저장한다.

                  기본형 변수는 값을 직접 저장한다.

 - 객체의 변수에 담지 않는 이유 : 객체는 하나의 변수에 담기에 너무 크고 유동적이기때문에 자바는 객체 접근을 위해 어드레싱(addresing) 방식 즉, 주소지를 통한 접근 방식을 취한다.

 

4. static 키워드
 - static은 '공유'의 개념을 담기에 클래스의 필드와 메소드에 적용될 수 있다. 

 

 


 - 클래스 변수 vs 인스턴스 변수
   클래스 변수(static 필드)는 클래스 영역에 존재한다. 객체 외부에 존재하므로 여러 객체가 공유에 좋다.
   이와 반대로 non-static 필드는 "인스턴스 변수"라 부른다. 인스턴스 변수는 각 객체 내부에 존재한다.

 

 

 

      

 

 

클래스 변수와 인스턴수 변수 선언 예

  1. public class Main {
  2.   public static void main(String[] args) {
  3.      Student std0 = new Student(2019122104, "Park");
  4.      Student std1 = new Student(2019206028, "Kim");
  5.      Student std2 = new Student(2019153237, "Lee");
  6.   }
  7. }
  8.  
  9. class Student {
  10.   // 클래스 변수
  11.   static int count = 0;
  12.  
  13.   // 인스턴스 변수
  14.   int id;
  15.   String name;
  16.  
  17.   // 생성자
  18.   Student (int i, String s) {
  19.     id = i;
  20.     name = str;
  21.     count++;
  22.   }
  23. }

 

 - 클래스 메소드 vs 인스턴스 메소드
   클래스 메소드(static 메소드)는 주체 객체 없이 실행된다. 간편한 기능 구현에 좋다.

 

 

클래스 메소드의 예

// Math의 static 메소드 random()을 호출
double rand = Math.random();

 

인스턴스 메소드의 예 (주체 객체를 통해 수행)

// 인스턴스 메소드를 수행하려면 먼저, 주체 객체가 생성되야 한다.
Student std4 = new Student(2007122104, "Choi");

 

// std4 변수에 연결된 객체가 주체가 되어, 인스턴스 메소드를 수행
std4.study();


5. 요약

 

 

 

6. 개념실습

 

 

 

1. 한 주간 일한 시간
public class EmployeeTest {
  public static void main(String[] args) {
    // 배열 생성
    int[] hours0 = { 2, 4, 3, 4, 5, 8, 8 };
    int[] hours1 = { 2, 4, 3, 4, 5, 8, 2 };
    int[] hours2 = { 2, 4, 3, 4, 5, 2 };
    int[] hours3 = { 2, 4, 3, 4, 5, 8, 5 };
    int[] hours4 = { 2, 4, 3, 4, 5, 8, 6 };
    int[] hours5 = { 2, 4, 3, 4, 5, 2, 8 };
    int[] hours6 = { 2, 4, 3, 7, 5, 8, 8 };
    int[] hours7 = { 2, 4, 3, 4, 5, 8, 8, 7 };
    
    // 객체 생성
    Employee e0 = new Employee("직원0", hours0);
    Employee e1 = new Employee("직원1", hours1);
    Employee e2 = new Employee("직원2", hours2);
    Employee e3 = new Employee("직원3", hours3);
    Employee e4 = new Employee("직원4", hours4);
    Employee e5 = new Employee("직원5", hours5);
    Employee e6 = new Employee("직원6", hours6);
    Employee e7 = new Employee("직원7", hours7);

    // 객체 배열 만들기
    Employee[] employees = { e0, e1, e2, e3, e4, e5, e6, e7 };
    
    // 정보 출력
    for (int i = 0; i < employees.length; i++) {
      employees[i].printTotalHours();
    }
  }
}

// 직원 클래스
class Employee {
  // 필드
  String name; // 이름
  int[] hours; // 요일별 일한 시간
  
  // 생성자
  Employee(String str, int[] arr) {
    name = str;
    hours = arr;
  }
  
  // 메소드
  void printTotalHours() {
    System.out.printf("%s -> %d 시간\n", name, totalHours());
  }
  
  int totalHours() {
    int sum = 0;
    for (int i = 0; i < hours.length; i++) {
      sum += hours[i];
    }
    return sum;
  }
}


2. 양궁 국가대표 선발전
public class PlayerTest {
  public static void main(String[] args) {
    // 점수 배열 생성
    int[] points0 = { 10, 9, 9, 8 };
    int[] points1 = { 9, 10, 9, 9 };
    int[] points2 = { 10, 9, 10, 10 };
    
    // 선수 객체 생성
    Player p0 = new Player("Kim", points0);
    Player p1 = new Player("Lee", points1);
    Player p2 = new Player("Park", points2);
    
    // 객체 배열 만들기
    Player[] players = { p0, p1, p2 };
    
    // 선수별 총점 출력
    for (int i = 0; i < players.length; i++) {
      players[i].printTotalPoints();
    }
  }
}

class Player {
  // 필드
  String name;  // 이름
  int[] points; // 점수
  
  // 생성자
  Player(String str, int[] arr) {
    /* 1. 생성자를 완성하세요. */
    name = str;
    points = arr;
  }
  
  // 메소드
  void printTotalPoints() {
    /* 2. 형식 문자열을 만드세요. */
    System.out.printf("%s -> %d점\n", name, totalPoints());
  }
  
  int totalPoints() {
    /* 3. 총점을 반환하세요. */
    int totalPoint = 0;
    for(int i=0;i<points.length;i++){
      totalPoint += points[i];
    }
    return totalPoint;
  }
}


3. 객체 조합하기
public class TeamTest {
  public static void main(String[] args) {
    // 선수 객체 생성
    Player kim = new Player("Kim", new int[] { 9, 8, 10 });
    Player lee = new Player("Lee", new int[] { 10, 9, 10 });
    Player park = new Player("Park", new int[] { 8, 10, 9 });
    Player xiao = new Player("Xiao", new int[] { 10, 9, 10 });
    Player yu = new Player("Yu", new int[] { 8, 9, 10 });
    Player xui = new Player("Xui", new int[] { 8, 9, 9 });

    // 객체 배열 만들기
    Player[] koreaPlayers = { kim, lee, park };
    Player[] chinaPlayers = { xiao, yu, xui };
    
    // 팀 객체 생성
    Team korea = new Team("KOREA", koreaPlayers);
    Team china = new Team("CHINA", chinaPlayers);
    
    // 팀 점수 출력
    korea.printTeamPoints();
    china.printTeamPoints();
  }
}

// 팀 클래스
class Team {
  // 필드
  String nation;    // 나라
  Player[] players; // 선수들
  
  // 생성자
  Team (String str, Player[] arr) {
    nation = str;
    players = arr;
  }
  
  // 메소드
  void printTeamPoints() {
    int sum = 0;
    for (int i = 0; i < players.length; i++) {
      sum += players[i].totalPoints();
    }
    System.out.printf("%s -> %d points\n", nation, sum);
  }
}

// 선수 클래스
class Player {
  // 필드
  String name;  // 이름
  int[] points; // 득점 현황

  // 생성자
  Player (String str, int[] arr) {
    name = str;
    points = arr;
  }

  // 메소드
  int totalPoints() {
    int sum = 0;
    for (int i = 0; i < points.length; i++) {
      sum += points[i];
    }
    return sum;
  }
}


4. 클래스 변수 vs 인스턴스 변수
public class GalaxyTest {
  public static void main (String[] args) {
    // 5칸 크기의 객체 배열 생성
    Galaxy[] phones = new Galaxy[5];
    
    // 배열 속 객체 할당
    for (int i = 0; i < phones.length; i++) {
      phones[i] = new Galaxy();
    }
    
    // 모든 객체 정보 출력
    for (int i = 0; i < phones.length; i++) {
      phones[i].print();
    }
    System.out.println("=========================");
    
    /* 2. Galaxy 객체의 개수를 클래스 변수로 출력하세요.*/
    System.out.printf("Galaxy 객체의 개수: %d",phones.length);
  }  
}

// 클래스
class Galaxy {
  // 필드(인스턴스 변수)
  String serialNum; // 일련번호
  
  /* 1. 해당 필드를 클래스 변수화 하세요. */
  static int count = 0;
  
  // 생성자
  Galaxy() {
    count++;
    char c = randomAlphabet(); // A ~ Z 중 택1
    serialNum = String.format("%c-%d", c, count);
  }
  
  // 메소드
  char randomAlphabet() {
    return (char) ('A' + Math.random() * 26); // A to Z
  }
  
  void print() {
    System.out.printf("Galaxy { serialNum: %s }\n", serialNum);
  }
}


5. 4가지 맛 붕어빵
public class FishBreadTest {
  public static void main(String[] args) {
    // 객체 배열 생성
    FishBread[] breads = new FishBread[4];
    
    /* 1. 붕어빵 객체를 팥/고구마/치즈/슈크림 순으로 만드시오. */
    breads[0] = new FishBread(0); // 팥 붕어빵
    breads[1] = new FishBread(1); // 고구마 붕어빵
    breads[2] = new FishBread(2); // 치즈 붕어빵
    breads[3] = new FishBread(3); // 슈크림 붕어빵
    
    // 모든 붕어빵 객체 정보 출력
    for (int i = 0; i < FishBread.count; i++) {
      breads[i].print();
    }
    System.out.println("==============");
    
    /* 2. 전체 붕어빵 객체 수를 출력하시오. */
    System.out.printf("붕어빵 객체 수: %d",FishBread.count);
  }
}

class FishBread {
  // 인스턴스 변수(non-static 필드)
  String contents;  // 내용물
  
  // 클래스 변수(static 필드)
  static int count; // 붕어빵 객체 수
  
  // 생성자
  public FishBread(int n) {
    // 내용물 선택 - 0: 팥, 1: 고구마, 2: 치즈, 3: 슈크림
    String[] arr = {"팥", "고구마", "치즈", "슈크림"};
    contents = arr[n];

    // 붕어빵 객체 수 카운팅
    FishBread.count++;
  }
  
  // 메소드
  void print() {
    System.out.printf("[%s] 붕어빵\n", contents);
  }
}


6. 클래스 메소드 호출
public class CircleTest {
  public static void main(String[] args) {
    // 객체 생성
    Circle c1 = new Circle(0, 0, 3); // 중심(0,0) - 반지름3
    Circle c2 = new Circle(2, 3, 4); // 중심(2,3) - 반지름4
    
    /* 1. 클래스 메소드를 호출하여 원의 넓이를 구하세요. */
    double area1 = Circle.area(c1);
    double area2 = Circle.area(c2);
    
    // 결과 출력
    System.out.printf("%s => 넓이: %.2f\n", c1.toStr(), area1);
    System.out.printf("%s => 넓이: %.2f\n", c2.toStr(), area2);
  }
}

class Circle {
  // 필드
  int x; // 원의 중심 - X 좌표
  int y; // 원의 중심 - Y 좌표
  int r; // 반지름

  // 생성자
  Circle(int centerX, int centerY, int radius) {
    x = centerX;
    y = centerY;
    r = radius;
  }

  // 인스턴스 메소드
  String toStr() {
    return String.format("Circle { 중심: (%d, %d), 반지름: %d }", x, y, r);
  }
  
  // 클래스 메소드
  static double area(Circle c) {
    // 원의 넓이 = 원주율 x 반지름 x 반지름
    return Math.PI * c.r * c.r;
  } 
}


7. 리뷰: 두 점 사이의 거리
public class PointTest {
  public static void main(String[] args) {
    // 객체 생성
    Point p1 = new Point(0, 0);
    Point p2 = new Point(3, 4);
    
    // 거리 계산
    double dist = Point.distance(p1, p2);
    
    // 결과 출력
    System.out.printf("두 점 A%s, B%s 사이의 거리: %.2f", p1.toStr(), p2.toStr(), dist);
  }
}

class Point {
  /* 1. 필드를 만드시오. */
  int x;
  int y;
  
  /* 2. 생성자를 정의하시오. */
  Point (int xn, int yn) {
    x = xn;
    y = yn;
  }
  
  /* 3. 객체 정보를 문자열로 반환하는 인스턴스 메소드를 만드시오. */
  String toStr(){
    return String.format("(%d, %d)", x, y);
  }
  
  /* 4. 두 점 사이의 거리를 반환하는 클래스 메소드를 만드시오. */
  static double distance(Point p, Point q){
   double dX = p.x - q.x;
   double dY = p.y - q.y;
   return Math.sqrt((dX * dX) + (dY * dY));
  }
}

 


추가내용

 

String은 레퍼런스형 타입 중에 클래스형입니다.

 

String 클래스의 특징 2가지

1. 문자형 배열(char[])과 그에 관련된 메서드들이 정의되어 있습니다.

 

 

 

2. String은 문자열을 읽어올 수만 있고, 변경할 수 없는 (immutable) 객체이기 때문에

   값을 바꾸는 경우에 새로운 String 객체 인스턴스가 생성됩니다.

 

  1-1) 문자열 값이 동일하다면 String 객체를 공유하도록 되어있습니다.
  1-2) new 연산자는 힙 영역에 새로운 객체를 만들 때 사용하기 때문에 new String을 하는 경우 문자열의 내용이 동일하더라도 서로 다른 객체를 참조합니다.
  1-3) 따라서 문자열의 내용만 비교할때는 String 객체의 equals 메소드를 사용해야 됩니다.

 

 

 

기타. 문자열을 기본형처럼 사용하고 싶다면 StringBuffer 클래스를 사용해야 됩니다.

        왜냐하면 StringBuffer 클래스는 String과 다르게 변경이 가능 (mutable) 하기 때문입니다.

        연산이 필요할때 크기를 변경시켜서 문자열을 변경하며, 문자열 연산이 자주 있을 때 String 보다 성능이 좋습니다.

        성능의 차이가 있는 이유는 String의 경우 새로운 인스턴스 생성시 이전에 참조하던 값은 쓰레기가 되면서 나중에 가비지 컬렉션에 의해 처리되는 시간이 있기 때문입니다.

 

Static 영역 데이터의 장점 및 단점

 1) 장점 : 프로그램이 종료될 때까지 어디서든 사용이 가능

 2) 단점 : 무분별하게 많이 사용하면 메모리가 부족


강의 출처 : cloudstudying.kr/lectures/198

728x90
반응형


Comments