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

국비 지원 개발자 과정_Day14

by 루팽 2022. 12. 15.

Car myCar = new Sonata //선언과 생성 이름 다를 수 있음 → 다형성

다형성

하나의 객체가 여러 가지 타입을 가질 수 있는 것

부모-자식 상속관계에 있는 클래스에서, 상위 클래스가 동일한 메시지로 하위 클래스들을 서로 다르게 동작시키는 객체 지향 원리

하나의 타입으로 다양한 실행 결과를 얻을 수 있어 객체를 부품화하여 유지 보수하기 용이함

 

생성자

디폴트 생성자는 생략이 가능하다

파라미터를 갖는 생성자는 생략이 불가하다

생성자가 하나라도 생성되어 있으면 디폴트 생성자를 만들어주지 않는다

생성자의 제1역할은 전역 변수의 초기화이다

package dev_java.week3;

class A {
  int i = 1;
  Amain aMain = null;

  public A(Amain aMain) {
    System.out.println("A(AMain aMain) 호출");
    this.aMain = aMain; // 주석으로 막으면 초기화x, NullPointerException
  }

  void methodB() {
    aMain.methodA();
  }
}

public class Amain {
  A a = new A(this);

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

  public static void main(String[] args) {
    Amain aMain = new Amain();
    aMain.a.methodB();
  }
}

 

깊은 복사

실제 값을 새로운 메모리 공간에 복사하는 것

복사한 객체를  변경해도 기존의 객체는 변경되지 않음

 

얕은 복사

주소 값을 복사하는 것

주소 값을 복사하기에 참조하고 있는 실제 값은 같음

복사한 객체가 변경되면 기존의 객체도 변경됨

package dev_java.week3.tables;

import java.util.Arrays;

/*
 * 배열 복사의 두 가지
 * 얕은 복사
 * 주소값 복사, 참조하는 실제값은 같음
 * 복사된 배열이나 원본 배열이 변경될 때 서로간의 값이 같이 바뀌는 것
 * 
 * 깊은 복사
 * 실제값을 새로운 메모리 공간에 복사
 * 복사본을 바꿔도 원본은 그대로
 */
 
public class ArrayCopy1 {
  void shallowCopy() {
    int[] org = { 1, 2, 3 };
    int[] org_copy = org; // 얕은 복사
    org_copy[2] = 5; // 카피를 바꿨을 때 원본도 바뀜
    for (int e : org) {
      System.out.print(e + " ");
    }
    System.out.println();
    for (int e : org_copy) {
      System.out.print(e + " ");
    }
    System.out.println("\n==========");
  }

  void deepCopy() {
    int[] org = { 1, 2, 3 };
    int[] org_copy = org.clone(); // 깊은 복사
    org_copy[2] = 5; // 카피를 바꿔도 원본을 그대로
    for (int e : org) {
      System.out.print(e + " ");
    }
    System.out.println();
    for (int e : org_copy) {
      System.out.print(e + " ");
    }
    System.out.println("\n==========");
  }

  void deepCopy2() {
    int[] org = { 1, 2, 3, 4, 5 };
    int[] org_copy = Arrays.copyOf(org, 2); // 2개만 복사됨, 원본은 그대로
    org_copy[1] = 5; // 인덱스1은 5로 변경
    for (int e : org) {
      System.out.print(e + " ");
    }
    System.out.println();
    for (int e : org_copy) {
      System.out.print(e + " ");
    }
    System.out.println("\n==========");
  }

  public static void main(String[] args) {
    ArrayCopy1 ac1 = new ArrayCopy1();
    ac1.shallowCopy();
    ac1.deepCopy();
    ac1.deepCopy2();
  }
}

// 1 2 5 
// 1 2 5
// ==========
// 1 2 3
// 1 2 5
// ==========
// 1 2 3 4 5
// 1 5
// ==========

 

package dev_java.week3.tables;

public class StringCopy {
  public static void main(String[] args) {
    String str = "Hello";
    String str1 = "Hello";
    System.out.println(str == str1); // true, 주소번지가 같다
    System.out.println(str.equals(str1)); // true, 주소번지가 가리키는 값(Hello)이 같다

    String str2 = new String("Hello");
    String str3 = new String("Hello");
    System.out.println(str2 == str3); // false, new를 사용했기에 주소번지가 다르가
    System.out.println(str2.equals(str3)); // true, 그 안의 값(Hello)은 같다
  }
}

 

package dev_java.week3.tables;

public class DeptVO {
  private int deptno;
  private String dname;
  private String loc;

  public int getDeptno() {
    return this.deptno;
  }

  public void setDeptno(int deptno) {
    this.deptno = deptno;
  }

  public String getDname() {
    return this.dname;
  }

  public void setDname(String dname) {
    this.dname = dname;
  }

  public String getLoc() {
    return this.loc;
  }

  public void setLoc(String loc) {
    this.loc = loc;
  }
}

 

package dev_java.week3.tables;

import javax.swing.JFrame;
import javax.swing.table.DefaultTableModel;

public class DeptTable2 extends JFrame { // DeptTable1 is a JFrame
  // 선언부
  String header[] = { "부서번호", "부서명", "지역" };
  String datas[][] = new String[1][3];
  DefaultTableModel dmt_dept = new DefaultTableModel(datas, header);

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

  public DeptTable2(String title) {
  }

  public DeptTable2(int i) {
  }

  // 화면그리기
  public void initDisplay() {
    this.setTitle("부서관리 시스템 Ver1.0");
    this.setSize(500, 400);
    this.setVisible(true);
  }

  // 메인메소드
  public static void main(String[] args) {
    new DeptTable2(null); // String의 디폴트값 null, 2번째 생성자 호출
    new DeptTable2(5); // 3번째 생성자 호출
  }
}

 

package dev_java.week3.tables;

import java.awt.Color;
import java.awt.FlowLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

// 이른 인스턴스화, 게으른 인스턴스화 -> 나눠보기 추가 연습
// 어떤 클래스를 상속받을 때에는 extends 예약어를 사용한다.
// A is a B 관계이면 상속으로 처리한다.
// 소나타는 자동차이다 -> 상속관계
// 작은 범위는 큰 범위다
// 부모클래스가 가진 변수와 메소드도 사용 가능하다. -> 자손이 더 많이 누릴 수 있다.
public class DeptTable1 extends JFrame { // DeptTable1 is a JFrame
  // 선언부
  String header[] = { "부서번호", "부서명", "지역" };
  String datas[][] = new String[1][3];
  // this는 사용되는 클래스 영역에서 선언된 클래스를 카리킨다
  // 그러면 여기서는 DeptTable1 타입인 것
  // 그런데 DefaultTableModel은 자바에서 제공되는 클래스이다(생성자도 정해져 있음)
  // 생성자는 메소드 오버로딩 규칙을 따른다(파라미터의 개수나 타입이 달라야함)
  // this를 파라미터에 넣는다면, 제공되는 생성자에 없음 -> 결국 사용 못함 -> 컴파일 에러(문법에러 발생)
  DefaultTableModel dmt_dept = new DefaultTableModel(datas, header); // DefaultTableModel 생성자 호출
  JTable jtb_dept = new JTable(dmt_dept);
  JScrollPane jsp_dept = new JScrollPane(jtb_dept,
      JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
      JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
  JPanel jp_north = new JPanel();
  JButton jtbn_sel = new JButton("선택");
  JButton jtbn_ins = new JButton("입력");
  JButton jtbn_upd = new JButton("수정");
  JButton jtbn_del = new JButton("삭제");

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

  // 화면그리기
  public void initDisplay() {
    this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    jp_north.setLayout(new FlowLayout(FlowLayout.RIGHT));
    // 버튼 색 설정
    jtbn_sel.setBackground(new Color(158, 9, 9));
    jtbn_sel.setForeground(Color.WHITE);
    jtbn_ins.setBackground(new Color(19, 99, 57));
    jtbn_ins.setForeground(Color.WHITE);
    jtbn_upd.setBackground(new Color(54, 54, 54));
    jtbn_upd.setForeground(Color.WHITE);
    jtbn_del.setBackground(new Color(7, 84, 170));
    jtbn_del.setForeground(Color.WHITE);
    // 버튼 추가
    jp_north.add(jtbn_sel);
    jp_north.add(jtbn_ins);
    jp_north.add(jtbn_upd);
    jp_north.add(jtbn_del);
    // this(상속받은 JFrame)에 추가
    this.add("North", jp_north);
    this.add("Center", jsp_dept);
    this.setTitle("부서관리 시스템 Ver1.0");
    this.setSize(500, 400);
    this.setVisible(true);
  }

  // 메인메소드
  public static void main(String[] args) {
    new DeptTable1();
  }
}

 

Vector

java.util패키지에 소속된 Collection 프레임워크의 일부

ArrayList와 마찬가지로 Vector 내부에 값이 추가되면 자동으로 크기가 조절됨

ArrayList와 다른 점은 Vector는 동기화된 메소드로 구성되어있기에 하나의 스레드를 실행 완료해야만 다른 스레드를 실행할 수 있다는 것(자동동기화)

그렇기에 멀티 스레드 환경에서 안전하게 객체 추가, 삭제가 가능

Vector v = new Vector(); // 타입 미설정 Object로 선언됨
Vector<Student> student = new Vector<Student>(); // Student객체만 사용가능
Vector<Integer> num2 = new Vector<Integer>(); // int타만 사용가능
Vector<Integer> num3 = new Vector<>(); // new에서 타입 파라미터 생략가능
Vector<String> v2 = new Vector<String>(10); // 초기 용량 지정
Vector<Integer> v3 = new Vector<Integer>(Arrays.asList(1,2,3)); // 초기값 지정

 

package dev_java.week3.tables;

import java.util.Vector;

public class Vector1 {
  public static void main(String[] args) {
    Vector v = new Vector(); // <>안의 타입을 명시하지 않음(불편함)
    Vector<String> v2 = new Vector<>(); // 벡터는 오브젝트 단위로 담을 수 있다
    v2.add("안녕");
    v2.add("2");
    Vector<Integer> v3 = new Vector<>(); // 원시형은 안되지만 래퍼클래스는 가능
    Vector<DeptVO> v4 = new Vector<>(); // 3차배열은 안쓴다(직관적x)

    // v.add(1); // 오토박싱, v.add(new Integer(1))와 같음(int를 Integer로)
    v.add("안녕"); // v.get(0)
    v.add(1); // v.get(1)
    System.out.println(v.size()); // 2
    System.out.println(v.get(0)); // 안녕
    System.out.println(v.get(1)); // 1

    String insa = (String) v.get(0); // 타입이 안맞음!, 강제형전환 필요
    System.out.println(insa); // 안녕
    String insa2 = v2.get(0);
    System.out.println(insa2); // 안녕

    if (v.get(1) instanceof Integer) {
      System.out.println("정수형입니다.");
    }
    if (v.get(0) instanceof String) {
      System.out.println("문자열입니다.");
    }
  }
}

 

package dev_java.week3.tables;

import java.util.Vector;

public class Vector2 {
  public static void main(String[] args) {
    Vector<String> v = new Vector<>();
    v.add("사과"); // 인덱스0
    v.add("토마토"); // 인덱스1
    v.add(1, "바나나"); // 인덱스1에 바나나넣기(배열과 다르게 끼워넣기 가능)
    for (int i = 0; i < v.size(); i++) {
      System.out.println(v.get(i)); // 사과, 바나나, 토마토
    }
  }
}

 

package dev_java.week3.tables;

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.dnd.DropTarget;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

// 이른 인스턴스화, 게으른 인스턴스화 -> 나눠보기 추가 연습
// 어떤 클래스를 상속받을 때에는 extends 예약어를 사용한다.
// A is a B 관계이면 상속으로 처리한다.
// 소나타는 자동차이다 -> 상속관계
// 작은 범위는 큰 범위다
// 부모클래스가 가진 변수와 메소드도 사용 가능하다. -> 자손이 더 많이 누릴 수 있다.
// ActionListener-인터페이스(단독으로 인스턴스화가 불가, 구현체 클래스가 필요함)
// 추상 메소드를 선언하고있다.
// ActionListener al = new DeptTable3(); -> 선언부와 생성부가 다를 수 있다(이럴때만 다형성이 가능함)
// 선언부와 생성부가 다르다 -> 동일한 메소드를 호출했는데 다른 기능이 처리되었다(다형성)
// 추상클래스도 구현체클래스가 필요하다 - this
// Duck myDuck = new WoodDuck(); -> myDuck.fly(); -> 비행x
// Duck herDuck = new RubberDuck(); -> herDuck.fly(); -> 비행x
// Duck himDuck = new MallardDuck(); -> himDuck.fly(); -> 비행가능!
public class DeptTable3 extends JFrame implements ActionListener { // DeptTable1 is a JFrame
  // 선언부
  String header[] = { "부서번호", "부서명", "지역" };
  String datas[][] = new String[0][3]; // 디폴트값 null
  // this는 사용되는 클래스 영역에서 선언된 클래스를 카리킨다
  // 그러면 여기서는 DeptTable1 타입인 것
  // 그런데 DefaultTableModel은 자바에서 제공되는 클래스이다(생성자도 정해져 있음)
  // 생성자는 메소드 오버로딩 규칙을 따른다(파라미터의 개수나 타입이 달라야함)
  // this를 파라미터에 넣는다면, 제공되는 생성자에 없음 -> 결국 사용 못함 -> 컴파일 에러(문법에러 발생)
  DefaultTableModel dtm_dept = new DefaultTableModel(datas, header); // DefaultTableModel 생성자 호출
  JTable jtb_dept = new JTable(dtm_dept);
  JScrollPane jsp_dept = new JScrollPane(jtb_dept,
      JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
      JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
  JPanel jp_north = new JPanel();
  JButton jtbn_sel = new JButton("조회");
  JButton jtbn_ins = new JButton("입력");
  JButton jtbn_upd = new JButton("수정");
  JButton jtbn_del = new JButton("삭제");
  // 부서목록 조회에 들어갈 샘플 데이터 생성
  String[][] depts = {
      { "10", "개발부", "서울" },
      { "20", "인사부", "인천" },
      { "30", "총무부", "부산" }
  };

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

  // 화면그리기
  public void initDisplay() {
    this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    jp_north.setLayout(new FlowLayout(FlowLayout.RIGHT));
    // 버튼 색 설정
    jtbn_sel.setBackground(new Color(158, 9, 9));
    jtbn_sel.setForeground(Color.WHITE);
    jtbn_ins.setBackground(new Color(19, 99, 57));
    jtbn_ins.setForeground(Color.WHITE);
    jtbn_upd.setBackground(new Color(54, 54, 54));
    jtbn_upd.setForeground(Color.WHITE);
    jtbn_del.setBackground(new Color(7, 84, 170));
    jtbn_del.setForeground(Color.WHITE);
    // 버튼 추가
    jp_north.add(jtbn_sel);
    jp_north.add(jtbn_ins);
    jp_north.add(jtbn_upd);
    jp_north.add(jtbn_del);
    // 이벤트리스너 연결
    jtbn_sel.addActionListener(this);
    jtbn_ins.addActionListener(this);
    jtbn_upd.addActionListener(this);
    jtbn_del.addActionListener(this);
    // this(상속받은 JFrame)에 추가
    this.add("North", jp_north);
    this.add("Center", jsp_dept);
    this.setTitle("부서관리 시스템 Ver1.0");
    this.setSize(500, 400);
    this.setVisible(true);
  }

  // 메인메소드
  public static void main(String[] args) {
    new DeptTable3();
  }

  @Override
  public void actionPerformed(ActionEvent e) {
    Object obj = e.getSource();
    if (obj == jtbn_sel) { // 조회버튼을 눌렀을 때
      while (dtm_dept.getRowCount() > 0) { // 먼저 원래 있던 것들을 지우기
        dtm_dept.removeRow(0);
      }
      for (int x = 0; x < depts.length; x++) {
        Vector<String> oneRow = new Vector<>(); // 벡터로 한 열씩 담기
        oneRow.add(depts[x][0]); // 부서번호
        oneRow.add(depts[x][1]); // 부서명
        oneRow.add(depts[x][2]); // 지역
        dtm_dept.addRow(oneRow);
      }
      for (int i = 0; i < depts.length; i++) {
        for (int j = 0; j < depts[i].length; j++) {
          // System.out.print(depts[i][j] + " "); // ln을 빼서 i인덱스의 j를 연이어 출력
          dtm_dept.setValueAt("여기", 1, 1); // 내용 수정 setValueAt
          System.out.println(dtm_dept.getValueAt(i, j)); // 내용 출력
        } // end of inner for문
        System.out.println();
      } // end of outter for문
      // DefaultTableModel에 데이터 초기화하기
    } else if (obj == jtbn_ins) {
      String[] temp = { "", "", "" };
      Vector<Object> oneRow = new Vector<>();
      oneRow.add(temp[0]);
      dtm_dept.addRow(oneRow);
    } else if (obj == jtbn_upd) {

    } else if (obj == jtbn_del) {
      int indexR = jtb_dept.getSelectedRow(); // 선택한 row
      int indexC = jtb_dept.getSelectedColumn(); // 선택한 column

      // Integer deptno = Integer.parseInt((String) dtm_dept.getValueAt(index, 0));
      // System.out.println(deptno);
      String deptinfo = (String) dtm_dept.getValueAt(indexR, indexC);
      System.out.println(deptinfo);

      // 하나씩 지우기
      dtm_dept.setValueAt("", indexR, indexC);

      // 한 행씩 지우기
      // dtm_dept.removeRow(indexR);
    }
  }
}

 

package dev_java.week3.example;

import java.util.Scanner;

// **연습문제1**
// 키보드로 부터 5개의 정수를 입력 받아서 배열에 저장하세요.
// 그리고 이들의 합계와 평균을 출력하는 프로그램을 작성하시오.
public class Exam1_221215_1 {
  // 배열 선언
  int users[] = new int[5]; // 0, 0, 0, 0, 0

  // 배열에 숫자 입력
  void initUsers() {
    Scanner s = new Scanner(System.in);
    for (int i = 0; i < users.length; i++) {
      System.out.print("숫자 5개를 입력해주세요. ");
      users[i] = s.nextInt();
      System.out.println(users[i]);

    }
    s.close();
  }

  // 총합 구하기
  int total() {
    int hap = 0; // 지역변수는 반드시 초기화를 해줘야한다
    for (int i = 0; i < users.length; i++) {
      hap += users[i];
    }
    return hap;
  }

  // 평균 구하기
  void average(int hap) {
    double avg = 0.0;
    avg = hap / (double) users.length;
    System.out.println("평균: " + avg);
  }

  public static void main(String[] args) {
    Exam1_221215_1 ex1 = new Exam1_221215_1();
    ex1.initUsers();
    int hap = ex1.total();
    System.out.println("총점: " + hap);
    ex1.average(hap);
  }
}

댓글