본문 바로가기
국비학원/수업기록

국비 지원 개발자 과정_Day11

by 루팽 2022. 12. 12.

배열은 클래스급 → new / 주소 번지-간접 참조 방식 / 전역 변수 scope, 지역변수 scope 구분 / 초기화

 

변수

같은 타입만 담을 수 있다

한 번에 하나의 값만 담을 수 있다

 

배열

같은 타입만 담을 수 있다

사이즈(길이)가 정해져있다(바꿀수없다)

한 번에 여러 값 담을 수 있다

 

객체 배열

배열과 같지만, 서로 다른 타입도 담을 수 있다.

 

 

 

도트 연산자(.) 뒤는 전역 변수

전역 변수만 인스턴스변수(소유주).변수명 형태로 호출할 수 있다

package dev_java.week3;

public class Main {
  int i = 1;

  public static void main(String[] args) {
    Sub sub = new Sub(); // 디폴트 생성자 호출
    System.out.println(sub.j); // j는 전역변수 2
    sub.methodA(); // sub methodA 호출
  }
}

 

package dev_java.week3;

public class Sub {
  int j = 2;

  void methodA() {
    System.out.println("sub methodA 호출");
  }
}

 

package dev_java.week3;

public class Main_1 {
  int i = 1;

  boolean isOk[] = new boolean[3]; // false, false, false
}

 

package dev_java.week3;

public class Sub_1 {
  public static void main(String[] args) {
    Main_1 m1 = new Main_1();
    for (int i = 0; i < m1.isOk.length; i++) {
      System.out.println(m1.isOk[i]); // false, false, false
    }
    System.out.println("==========");
    for (boolean isOk : m1.isOk) { // 개선된 for문
      System.out.println(isOk); // false, false, false
    }
  }
}

 

package dev_java.week3;

public class Main_2 {
  int i = 1;
  boolean isOk[] = null; // 선언

  // 디폴트 생성자는 생략이 가능하다
  // 그러나 지금은 isOk배열의 생성을 위해서 getisOk()를 경유하도록해야
  // NullPointerException을 피할 수 있다
  public Main_2() {
    System.out.println("Main_2 디폴트 생성자 호출 성공");
    getisOK(); // 디폴트생성자에 getisOk 넣음
  }

  // 선언과 동시에 인스턴스화를 하지 않는 경우를 게으른 인스턴스화라고 한다.
  // 선언과 생성을 동시에 하지 않고 메소드를 통해서 객체 주입을 받을 수 있다.
  // 이럴 경우 메소드 안에서 if문을 통해 null체크를 할 수 있어 싱글톤 패턴으로 객체를
  // 주입받을 수 있기에 현업에서 선호하는 객체 주입 방법 중 하나이다.
  boolean[] getisOK() {
    if (isOk == null) {
      isOk = new boolean[] { true, false, true }; // 생성, 초기화
    }
    return isOk;
  }
}

 

package dev_java.week3;

public class Sub_2 {
  public static void main(String[] args) {
    Main_2 m2 = new Main_2(); // 인스턴스화, Main_2의 디폴트 생성자에 getisOk를 넣었기에 null이 아닌 값이 나옴!
    for (int i = 0; i < m2.isOk.length; i++) {
      System.out.println(m2.isOk[i]);
    }
    System.out.println("==========");
    for (boolean isOk : m2.isOk) {
      System.out.println(isOk);
    }
  }
}

// Main_2 디폴트 생성자 호출 성공
// true      
// false     
// true      
// ==========
// true      
// false     
// true

 

인터페이스

단독 인스턴스화 x → 추상메소드만 가지고 있기에 반드시 구현체 클래스 있어야 함(implements)

인터페이스 중심 코딩은 재사용성 높이고 결합도 낮춘다.(추상메소드 오버 라이딩)

ActionListener(인터페이스) → 구현체 클래스(이벤트 핸들러 클래스)가 필요함 →메소드 오버라이드를 해야 함(actionPerformed)

 

추상메소드 선언();

추상메소드 선언은 인터페이스 안에서 일어난다.(인터페이스의 메소드는 추상메소드이다)

추상메소드는 호출이 아니라 선언이라도 세미콜론(;)으로 끝난다.

정의할 수 없다(장치가 결정되지 않음) → 재정의해야 한다 (메소드 오버 라이딩)

메소드 오버라이드는 선언부를 절대로 수정할 수 없다

 

@annotation

사전적 의미는 주석

메타데이터의 일종(컴파일, 실행 과정에서 코드를 어떻게 처리해야 하는지 알려주기 위한 추가 정보)

@Override →선언한 메서드가 오버라이드 되었다는 걸 나타냄 

 

package dev_java.week3;

import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class JTextAreaUI implements ActionListener {
   // 선언부
   JTextAreaUILogic jtaUILogic = new JTextAreaUILogic(this);
   // 인터페이스는 반드시 구현체 클래스가 있어야 한다.
   // 단독으로 인스턴스화할 수 없다.
   // ActionListener al = new ActionListener(); //단독으로 인스턴스화 불가!
   // 선언부와 생성부의 타입이 다르다. 그렇기에 다형성이 가능함(폴리모피즘)재사용성을 높이고 결합도는 낮춘다.
   // ActionListener al = new JTextAreaUI(); //이렇게는 가능!
   JFrame jf = new JFrame();
   JTextArea jta = new JTextArea(10, 20);
   JTextField jtf = new JTextField(10);

   // 디폴트 생성자는 생략이 가능하다. -> JVM이 대신 생성해줌
   // 생성자도 메소드처럼 호출이 가능하다. 하지만 메소드와 다르게 리턴타입이 없다
   // 인스턴스화(호출) 될 때 생성된다.
   public JTextAreaUI() { // 디폴트 생성자 선언
      initDisplay();
   }

   public void initDisplay() { // UI를 그린다(이벤트처리)
      // 이벤트 소스와 이벤트 핸들러 클래스 매핑(매칭)하기
      jtf.addActionListener(this); // this는 나 자신, 이벤트 핸들러 클래스의 주소번지
      // 멀티라인 작성 가능한 컴포넌트의 배경색 설정
      jta.setBackground(Color.cyan);
      // JFrame은 디폴트 레이아웃이 BorderLayout이라서 동, 서, 남, 북, 중앙 배치 가능
      jf.add("Center", jta); // JTextArea는 중앙에 배치
      jf.add("South", jtf); // JTextField는 남쪽에 배치
      jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 윈도우창 x버튼 클릭 시 자원회수
      jf.setSize(400, 300); // 윈도우창 가로 세로 크기 설정
      jf.setVisible(true); // 화면을 출력함
   }

   public static void main(String[] args) { // 가장먼저 호출됨-entry point
      new JTextAreaUI(); // 생성자가 호출되고 그 안에서 화면그리는 메소드 호출
   }

   // annotation-문법제약을 갖고있다-선언부가 일치해야한다.
   @Override
   public void actionPerformed(ActionEvent e) { // callback 추상메소드, 이벤트가 감지됐을 때 호출됨
      // 추상메소드의 파라미터를 통해서 감지된 컴포넌트의 주소번지를 얻어오는
      // getSource메소드의 소유주(ActionEvent클래스)
      Object obj = e.getSource();
      if (jtf == obj) { // JTextField에 엔터를 쳤는가?
         // JTextField에 입력한 문자열받기
         String input = jtf.getText();
         jta.append("JTextAreaUI원본: " + input + "\n"); // 원본에서 찍히는지 확인
         jtaUILogic.account(input); //Logic에서 가져온 값
         jtf.setText("");
      }
   }
}

 

package dev_java.week3;

public class JTextAreaUILogic {
  // 여기서 직접 인스턴스화하면 복제본이 만들어짐-복제본에 출력된다
  // 메모리 StackOverFlow발생-서버가 중지됨
  // JTextArea jta = new JTextArea(10, 20); // 복제본이 생성되서 원본작동x + 서버부담
  JTextAreaUI jtaUI = null;

  public JTextAreaUILogic(JTextAreaUI u1) {
    // 생성자 안에서 JTextAreaUI의 JTextArea원본과 전역변수를 초기화해줘야함
    this.jtaUI = u1;
  }

  public void account(String input) {
    // JTextAreaUI클래스에 정의된 주소번지(원본)를 사용
    jtaUI.jta.append("UILogic: " + input + "\n");
  }
}

 

 

뷰와 핸들러 분리 예제

 

package dev_java.week3;

import javax.swing.JButton;
import javax.swing.JFrame;

public class JButtonUI {
  // 선언부
  JFrame jf = new JFrame();
  JButton jbtn_south = new JButton("전송");
  JButtonUIEvent jButtonEvent = new JButtonUIEvent(this);

  // 생성자
  public JButtonUI() {
    initDisplay();
  }

  // 화면처리부
  public void initDisplay() {
    // 이벤트 소스와 이벤트 핸들러 매핑시 this를 쓸 수 있는 건
    // 오직 내 안에 actionPerformed가 구현되어 있을때 뿐이다.
    jbtn_south.addActionListener(jButtonEvent); // 이벤트 핸들러 분리
    // 윈도우 x버튼 클릭시 자원반납(어플 정상 종료)
    jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jf.add("South", jbtn_south);
    jf.setSize(300, 250);
    jf.setVisible(true);
  }

  public static void main(String[] args) {
    new JButtonUI();
  }
}

 

package dev_java.week3;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class JButtonUIEvent implements ActionListener {
  JButtonUI jbUI = null;

  public JButtonUIEvent(JButtonUI jButtonUI) {
    this.jbUI = jButtonUI;
  }

  @Override
  public void actionPerformed(ActionEvent e) {
    Object obj = e.getSource();
    if (obj == jbUI.jbtn_south) {
      System.out.println(jbUI.jbtn_south.getText() + "버튼 클릭");
    }
  }
}

 

이벤트 핸들러 분리버전(뷰/로직/이벤트 핸들러)

package dev_java.week3;

import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class JTextAreaUI {
   // 선언부
   JTextAreaUILogic jtaUILogic = new JTextAreaUILogic(this); // 로직 분리
   JTextAreaUIEvent jTextAreaUIEvent = new JTextAreaUIEvent(this); // 이벤트핸들러 분리
   // 인터페이스는 반드시 구현체 클래스가 있어야 한다.
   // 단독으로 인스턴스화할 수 없다.
   // ActionListener al = new ActionListener(); //단독으로 인스턴스화 불가!
   // 선언부와 생성부의 타입이 다르다. 그렇기에 다형성이 가능함(폴리모피즘)재사용성을 높이고 결합도는 낮춘다.
   // ActionListener al = new JTextAreaUI(); //이렇게는 가능!
   JFrame jf = new JFrame();
   JTextArea jta = new JTextArea(10, 20);
   JTextField jtf = new JTextField(10);

   // 디폴트 생성자는 생략이 가능하다. -> JVM이 대신 생성해줌
   // 생성자도 메소드처럼 호출이 가능하다. 하지만 메소드와 다르게 리턴타입이 없다
   // 인스턴스화(호출) 될 때 생성된다.
   public JTextAreaUI() { // 디폴트 생성자 선언
      initDisplay();
   }

   public void initDisplay() { // UI를 그린다(이벤트처리)
      // 이벤트 소스와 이벤트 핸들러 클래스 매핑(매칭)하기
      jtf.addActionListener(jTextAreaUIEvent); // ()에 이벤트핸들러를 가리키는 인스턴스변수명이 와야함
      // 멀티라인 작성 가능한 컴포넌트의 배경색 설정
      jta.setBackground(Color.cyan);
      // JFrame은 디폴트 레이아웃이 BorderLayout이라서 동, 서, 남, 북, 중앙 배치 가능
      jf.add("Center", jta); // JTextArea는 중앙에 배치
      jf.add("South", jtf); // JTextField는 남쪽에 배치
      jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 윈도우창 x버튼 클릭 시 자원회수
      jf.setSize(400, 300); // 윈도우창 가로 세로 크기 설정
      jf.setVisible(true); // 화면을 출력함
   }

   public static void main(String[] args) { // 가장먼저 호출됨-entry point
      new JTextAreaUI(); // 생성자가 호출되고 그 안에서 화면그리는 메소드 호출
   }
}

 

package dev_java.week3;

public class JTextAreaUILogic {
  // 여기서 직접 인스턴스화하면 복제본이 만들어짐-복제본에 출력된다
  // 메모리 StackOverFlow발생-서버가 중지됨
  // JTextArea jta = new JTextArea(10, 20); // 복제본이 생성되서 원본작동x + 서버부담
  JTextAreaUI jtaUI = null;

  public JTextAreaUILogic(JTextAreaUI u1) {
    // 생성자 안에서 JTextAreaUI의 JTextArea원본과 전역변수를 초기화해줘야함
    this.jtaUI = u1;
  }

  public void account(String input) {
    // JTextAreaUI클래스에 정의된 주소번지(원본)를 사용
    jtaUI.jta.append("UILogic: " + input + "\n");
  }
}

 

package dev_java.week3;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class JTextAreaUIEvent implements ActionListener {
  JTextAreaUI jtaUI = null;

  public JTextAreaUIEvent(JTextAreaUI u1) {
    // 생성자 안에서 JTextAreaUI의 JTextArea원본과 전역변수를 초기화해줘야함
    this.jtaUI = u1;
  }

  // annotation-문법제약을 갖고있다-선언부가 일치해야한다.
  @Override
  public void actionPerformed(ActionEvent e) { // callback 추상메소드, 이벤트가 감지됐을 때 호출됨
    // 추상메소드의 파라미터를 통해서 감지된 컴포넌트의 주소번지를 얻어오는
    // getSource메소드의 소유주(ActionEvent클래스)
    Object obj = e.getSource();
    if (jtaUI.jtf == obj) { // JTextField에 엔터를 쳤는가?
      // JTextField에 입력한 문자열받기
      String input = jtaUI.jtf.getText();
      jtaUI.jta.append("JTextAreaUI원본: " + input + "\n"); // 원본에서 찍히는지 확인
      jtaUI.jtaUILogic.account(input); // Logic에서 가져온 값
      jtaUI.jtf.setText("");
    }
  }
}

 

또 다른 분리 예제(뷰/로직/이벤트 핸들러)

package dev_java.week3;

import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class JTextAreaUI2 {
  // 선언부
  JTextAreaUILogic2 jLogic2 = new JTextAreaUILogic2(this);
  JTextAreaUIEvent2 jEvent2 = new JTextAreaUIEvent2(this);
  JFrame jf = new JFrame();
  JTextArea jta = null;
  JScrollPane jsp = null;
  JTextField jtf = new JTextField(10);

  public JTextAreaUI2() {
    getTextArea();
    initDisplay();
  }

  public JTextArea getTextArea() {
    if (jta == null) {
      jta = new JTextArea(10, 20);
      jsp = new JScrollPane(jta, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    }
    return jta;
  }

  public void initDisplay() {
    jtf.addActionListener(jEvent2);
    jta.setBackground(Color.cyan);
    jf.add("Center", jsp); // jta가 아니라 jsp를 붙여줌(가장 밑에 있는 것)
    jf.add("South", jtf);
    jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jf.setSize(400, 300);
    jf.setVisible(true);
  }

  public static void main(String[] args) {
    new JTextAreaUI2();
  }
}

 

package dev_java.week3;

public class JTextAreaUILogic2 {
  JTextAreaUI2 jUI2 = null;

  public JTextAreaUILogic2(JTextAreaUI2 jUI2) {
    this.jUI2 = jUI2;
  }

  public void account(String input) {
    jUI2.jta.append("UILogic: " + input + "\n");
  }
}

 

package dev_java.week3;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class JTextAreaUIEvent2 implements ActionListener {
  JTextAreaUI2 jUI2 = null;

  public JTextAreaUIEvent2(JTextAreaUI2 jUI2) {
    this.jUI2 = jUI2;
  }

  @Override
  public void actionPerformed(ActionEvent e) {
    Object obj = e.getSource();
    if (jUI2.jtf == obj) {
      String input = jUI2.jtf.getText();
      jUI2.getTextArea().append("JTextAreaUI원본: " + input + "\n");
      jUI2.jLogic2.account(input);
      jUI2.jtf.setText("");
    }
  }
}

댓글