Java 9일차 : 내부클래스, 예외처리, 제너릭, 리스트

InstanceOf

  • 클래스타입비교
 [인스턴스명] instanceOf [클래스명]
  • 해당 인스턴스가 [클래스명]타입이면 true를 반환

예시

package test.day0415;

class TestA{
  public void writeA() {
    System.out.println("writeA");
  }
}

class TestB extends TestA{
  private void wirte() {
    System.out.println("sub writeA");
    super.writeA();
  }
  public void writeB() {
    System.out.println("writeB");
  }
}

class TestC{
  public void writeC() {
    System.out.println("writeC");
  }
}

public class InstanceOfEx1 {
  public static void instanceTest(Object ob) {
    System.out.println("TestA: " + (ob instanceof TestA));
    System.out.println("TestB: " + (ob instanceof TestB));
    System.out.println("TestC: " + (ob instanceof TestC));
    System.out.println();

  }

  public static void main(String[] args) {
    // TODO Auto-generated method stub
    TestA a  = new TestA();
    TestA a2 = new TestB();
    TestB b= new TestB();
    TestC c= new TestC();

    instanceTest(a); //자기보다 큰 범위일때만 true, 즉 TestA만 true
    instanceTest(a2); //TestA, TestB are true
    instanceTest(b); //TestA, TestC are true
    instanceTest(c); //Test C is true
  }
}

내부클래스

  1. 일반 내부클래스 : 말 그대로 클래스 내부에 클래스가 있는것

    class A{
      class B{
      }
    }
    

    예시

    package test.day0415;
       
    class OuterA{
      int a = 10;
      static int b = 20;
       
      class InnerA{
       
        int c = 30;
        // static int d = 40; //static class가 아닌 일반 내부클래스에서는 static 변수 사용불가 
        //외부클래스의 모든 변수 사용 가능
       
        public void disp() {
          System.out.println("a= " + a);
          System.out.println("b= " + b);
          System.out.println("c= " + c);
          System.out.println("=======");
        }
      } //일반적으로 내부클래스의 메서드는 메인클래스가 아니라 외부클래스에서 호출한다.
       
      public void write() {
       
        InnerA a = new InnerA();
        a.disp();
      }
    }
       
    public class InnerClassEx2 {
       
      public static void main(String[] args) {
        OuterA a = new OuterA();
        a.write();
        //만약 메인클래스에서 타 클래스의 내부 클래스를 호출하고 싶다면?
       
        OuterA.InnerA b = new OuterA().new InnerA();
        b.disp();
        //혹은 OuterA.InnerA b = a.new InnerA(); 로 만들어도 좋다. 물론 의미는 좀 다르지만...
        OuterA.InnerA c = a.new InnerA();
        a.a = 99;
        b.disp(); //여기에는 변수 a가 반영되지 않지만,
        c.disp(); //여기에는 변수 a가 반영된다.
      }
    }
       
    

    실제로 저장될때는 OuterA.class 와 OuterA$InnerA.class로 저장됨

  2. static 내부클래스

    예시

    package test.day0415;
       
    class OuterB{
      int a= 10;
      static int b = 20;
       
      //static 내부클래스 내에서는 static변수 선언 가능 
      static class InnerB{
       
        int c= 30;
        static int d=40;
       
        public void disp() {
          //System.out.println("a = " + a); //static 변수가 아닌 일반멤버변수는 호출이 안된다.
          System.out.println("b = " + b);
          System.out.println("c = " + c); //static클래스 내부의 일반변수는 static변수랑 같은건가? -> disp2 참고 
          System.out.println("d = " + d);
          System.out.println("=========");
       
        }
       
        public static void disp2() {
          //System.out.println("c = " + c); //static 클래스 내부의 일반 변수라고 해도 static 메서드에서 호출은 안됨.
          System.out.println("d = " + d);
        }
      }
       
      public void write() {
       
        InnerB ib = new InnerB();
        ib.disp();
      }
    }
       
    public class StaticInnerEx3 {
       
      public static void main(String[] args) {
        // TODO Auto-generated method stub
        OuterB ob = new OuterB();
        ob.write();
        //내부클래스가 static 클래스 일 때 직접 호출해보기
        OuterB.InnerB inB = new OuterB.InnerB(); //내부클래스 앞에 new가 없다.
        inB.disp();
      }
    }
    
  3. 익명 내부클래스

    • 익명이란? 이름이 없는 것을 의미한다. 이것을 자바의 프로그램적으로 해석하면 정의된 클래스의 이름이 없다는 것이 된다.

    • 내부 클래스긴 한데 새로 생성한것이 아니라, 타 클래스(인터페이스, 추상클래스 포함)를 생성해서 만든 클래스의 경우.
    • 반드시 오브젝트 생성시 클래스명(); 으로 끝나지 않고, 클래스명() { 내용 }; 으로 진행되어야 생성됨.

    예시

    package test.day0415;
       
    interface Apple{
      public void play();
    }
       
    abstract class Apple2{
      abstract public void draw();
    }
       
    class Apple3{
      public void run() {
      }
    }
       
    class Orange{
       
      Apple ap = new Apple() {
       
        @Override
        public void play() {
          System.out.println("익명 내부 클래스의 메서드 실행 ");
        }
      };
       
       
      Apple2 ap2 = new Apple2() {
       
        @Override
        public void draw() {
          System.out.println("추상 클래스로부터 만든 익명 내부 클래스 ");
        }
      };
       
       
      Apple3 ap3 = new Apple3() {
       
        public void run() {
          System.out.println("일반클래스로 부터 익명내부클래스 생성하기 ");
       
        }
      };
    }
       
    public class AnomInnerClassEx4 {
       
      public static void main(String[] args) {
        // TODO Auto-generated method stub
        Orange or = new Orange();
        or.ap.play();
        or.ap2.draw();
        or.ap3.run();
      }
    }
    

    실제 파일은

    Orange.class

    Orange$1.class

    Orange$2.class

    Orange$3.class 로 생성된다.

지금까지 배운 클래스에 대한 활용법을 공부하기 위해서 간단하게 GUI 프로그래밍 스윙을 공부해보자

package test.day0415;

import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.JFrame;

class MyFrame extends JFrame implements WindowListener{
  public MyFrame(String title) {
    super(title); //JFrame의 생성자를 사용하자.
    //시작위치 설정, 프레임의 너비와 높이 지정.
    this.setLocation(300, 100);
    this.setSize(800, 500);
    //프레임 보이도록 
    this.setVisible(true);
    this.addWindowListener(this);
  }

  @Override
  public void windowOpened(WindowEvent e) {
    // TODO Auto-generated method stub
  }

  @Override
  public void windowClosing(WindowEvent e) {
    // TODO Auto-generated method stub
    System.out.println("종료합니다.");
    System.exit(0);
  }

  @Override
  public void windowClosed(WindowEvent e) {
    // TODO Auto-generated method stub
  }

  @Override
  public void windowIconified(WindowEvent e) {
    // TODO Auto-generated method stub
  }

  @Override
  public void windowDeiconified(WindowEvent e) {
    // TODO Auto-generated method stub
  }

  @Override
  public void windowActivated(WindowEvent e) {
    // TODO Auto-generated method stub
  }

  @Override
  public void windowDeactivated(WindowEvent e) {
    // TODO Auto-generated method stub
  }
}
public class JframeSwingEx5 {
  public static void main(String arg[]) {
    MyFrame mf = new MyFrame("this is title!");
  }
}

package test.day0415;

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.JFrame;

class MyFrame2 extends JFrame{
  public MyFrame2(String title) {
    super(title); //JFrame의 생성자를 사용하자.
    //시작위치 설정, 프레임의 너비와 높이 지정.
    this.setLocation(300, 100);
    this.setSize(800, 500);
    //프레임 보이도록 
    this.setVisible(true);
    this.addWindowListener(new WindowExit()); // 만들어둔 오브젝트가 없다면 그냥 인자줄때 생성해버리자~!
  }
  //내부클래스 - 더이상 상속이 힘들기 때문..
  class WindowExit extends WindowAdapter{
    @Override
    public void windowClosing(WindowEvent e) {
      // TODO Auto-generated method stub
      System.out.println("종료합니다~!");
      System.exit(0);
    }
  }
}

public class JframeSwingEx6 {

  public static void main(String[] args) {
    // TODO Auto-generated method stub
    MyFrame2 mf2 = new MyFrame2("this is title!");
  }
}

Exception

  1. 일반적 예외 - ioexception => 반드시 처리

  2. 런타임 예외 - 실행시에 발생하는 exception

  • 가장 많이 발생하는 예외

    • NullPointerException : 객체 생성 없이 메서드를 호출할 때 발생
    • ArrayIndexOutOfBounceException : 배열에서 없는 번지를 접근하려할때 발생
    • NumberFormatException : Integer.parseInt(숫자 형태의 문자열을 정수타입으로 변환) 사용시에 많이 발생 (예 : 문자열에 공백이 포함되어 있거나 문자가 포함되어 있을 때)

형식

try{
  exception이 발생할만한 로직
}catch(exception종류 e){
  예외처리
}finally{
  예외 상관없이 무조건 실행될 명령 
}

예시

package test.day0415;
public class ExceptionEx7 {
  public static void main(String[] args) {
    // TODO Auto-generated method stub
    int arr[] = {4,5,6,8};
    for( int i = 0 ; i <= arr.length ; i++) {
      try {
        System.out.println(arr[i]);
      }catch(ArrayIndexOutOfBoundsException e) {
        System.out.println("배열인덱스가 잘못되었다." + e.getMessage());
      }
    }
    System.out.println("done!");
  }
}
import java.sql.Date;

public class ExceotionEx8 {

  public static void main(String[] args) {
    // TODO Auto-generated method stub
    Date date = null;
    String str = "12abc";
    try {
      date = new Date(2019,04,15);
      System.out.println("연도출력");
      System.out.println(date.getYear()); //여기서 예외발생 시 나머지 코드를 실행치 않고 바로 catch로 이동됨. 
      System.out.println("숫자변환");
      int n = Integer.parseInt(str);
      System.out.println(n);
    }catch(NullPointerException e1) {
      System.out.println("객체생성불가 " + e1.getMessage());
    }catch(NumberFormatException e2) {
      System.out.println("숫자변환시 문자가 섞여있음 " + e2.getMessage());
      e2.printStackTrace();
    }finally {
      System.out.println("무조건 실행되는 명령");
    }
    System.out.println("bye!");
  }
}
package test.day0415;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

class TestExcep{
  public void test1() throws ArrayIndexOutOfBoundsException, IOException{ //요걸 붙히면 try에서 호출된 곳으로 예외처리를 미룰 수 있다.
    int arr[] = {3,4,5,6};
    for(int i = 0 ; i<= arr.length ; i++) {
      System.out.println(arr[i]);
    }
    BufferedReader br = null;
    InputStreamReader is = null;
    br = new BufferedReader(new InputStreamReader(System.in));
    System.out.println("문자열을 입력하세요.");
    String str = null;
    str = br.readLine(); //일반적 예외는 반드시 throws를 클래스 선언시 넣거나, 해당 명령어에서 try/catch처리를 해줘야 한다.
    System.out.println("입력한 문자열: " + str);
  }
}

public class ExceptionEx9 {

  public static void main(String[] args) {
    // TODO Auto-generated method stub
    TestExcep ex = new TestExcep();
    try {
      ex.test1();
    }catch(ArrayIndexOutOfBoundsException e) {
      System.out.println("배열인덱스오류 ");
    } catch (IOException e) { //TestExcep 클래스에서 throws한 예외이므로 여기서 catch처리를 해준다.
      // TODO Auto-generated catch block
      System.out.println("IO예외");
      e.printStackTrace();
    }
    System.out.println("bye!");
  }
}

Throw

  • 강제로 예외를 발생시킬 때 사용한다
package test.day0415;

import java.util.Scanner;

//사용자 예외 클래스 구현 
class MyException extends Exception{
  public MyException(String err) {
    super(err);
  }

  public static void inputData() throws MyException
  {
    Scanner sc = new Scanner(System.in);
    String str;
    System.out.println("문자열 입력 ");
    str = sc.nextLine();

    if(str.contentEquals("바보")) {
      throw new MyException("욕은 안돼요!!!"); //강제로 예외 발생 

    }else {
      System.out.println("메세지는 " + str);
    }
  }
}

public class ExceptionEx10 {

  public static void main(String[] args) {
    // TODO Auto-generated method stub
    try {
      MyException.inputData();
    } catch (MyException e) {
      // TODO Auto-generated catch block
      System.out.println("오류메세지: " +e.getMessage()); //등록된 예외 메세지가 출력됨 
    }
    try {
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    System.out.println("bye!!");

  }
}

제네릭

  • 자료형에 어떤 객체를 담을지 명시
  • Generics는 컬렉션(자료구조) 즉, 쉽게 말해서 객체들을 저장(수집)하는 구조적인 성격을 보강하기 위해 제공되는 것이다.
  • 간단히 예를 들자면 컵이라는 특정 객체가 있다. 이 컵은 물만 담을 수 있는 물컵, 또는 이 컵은 주스만 담을 수 있는 주스 컵!이렇게 상징적인 것이 바로 Generics다!

Set

  • Set 인터페이스를 상속받은 HashSet : 중복자료를 허용하지 않으며 비순차적으로 데이타를 저장
Set<형태> 변수명 = new HashSet<형태>();
  • 주요 메서드 : add(object o), remove(index 혹은 object o), size()
package test.day0415;

import java.util.HashSet;
import java.util.Set;

public class SetEx11 {

  public static void main(String[] args) {
    // TODO Auto-generated method stub
    //<String> 제네릭 : String 타입만 담겠다. 
    Set<String> set = new HashSet<String>();
    set.add("apple");
    set.add("banana");
    set.add("Apple");
    set.add("apple"); //중복이므로 추가안됨 
    set.add("orange");
    //set.add(100); //String타입이 아니므로 에러 
    System.out.println(set.size());
    //set데이타 출력해보기
    for(String s:set) {
      System.out.println(s);
    } //순서는 지맘대로.... 
    Set<Integer> set2 = new HashSet<Integer>(); //뒤에는 반복해서 넣지말고 <>(); 라고만 해줘도 괜찮다.
    int arr[] = {4,1,2,5,64,3,3,3};
    for(int a:arr)
      set2.add(a); //5.0이후버전에서는 에러없음 : 자동으로 객체화됨(오토박싱)
    //5.0 이전버전에서는 set2.add(new Integer(a)); 라고 넣음
    for(int s2:set2) {
      System.out.println(s2);
    }
    set2.remove(4); //데이타 제거하기 
    System.out.println(set2.toString());
  }

Map

  • Map 인터페이스를 상속받은 클래스 HashMap : 키와 값의 쌍으로 저장하고자 할 때(이 때 키는 타입이 Set 으로 존재)
Map<K,V> map1 = new HashMap();
// 혹은
HashMap map2 = new HashMap2();
  • 주요 메서드 : put(K, V), get(K), size()

리스트

package test.day0415;

import java.util.ArrayList;
import java.util.Vector;

public class ArrayListEx13 {

  public static void main(String[] args) {
    // TODO Auto-generated method stub
    ArrayList<String> list = new ArrayList<String>(); 
    System.out.println(list.size());
    list.add("apple");
    list.add("banana");
    list.add("kiwi");
    list.add("banana");
    System.out.println(list.toString()); //중복허용이며 순서대로 나온다. <-> Set

    Vector<String> list2 = new Vector<String>();
    System.out.println(list2.size());
    System.out.println(list2.capacity()); //vector만 갖고있는 메서드 
    // 기본10개임. 선언시()안에 인자 줄 경우 그 수만큼 할당됨.
  }
}
package test.day0415;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

public class VectorEx14 {

  public static void main(String[] args) {
    // TODO Auto-generated method stub
    //List<String> list = new Vector<String>(); //둘 중 뭘 써도 괜찮다. 
    List<String> list = new ArrayList<String>();
    list.add("rose");
    list.add("tulip");
    list.add("daisy");
    list.add("sunflower");
    System.out.println("출력 1 ===========");
    for(String l:list)
      System.out.println(l);
    System.out.println("출력 2 ===========");
    for(int i = 0 ; i < list.size(); i++ ) {
      System.out.println(list.get(i));
    }
    System.out.println("출력 3 ===========");
    Iterator<String> iter = list.iterator();
    while(iter.hasNext()) {//다음 데이타가 있으면 참 
      System.out.println(iter.next());
    }
    System.out.println();
    list.remove(0); //0번째 데이타 삭제 
    System.out.println(list.toString());
    list.add(1, "kanna"); //1번째 데이타로 삽입됨 
    System.out.println(list.toString()); 
    list.clear(); //전체 삭제 
    System.out.println(list.toString()); 

  }
}
  • 여러개의 데이타를 클래스로 묶어서 Vector에 저장하는 예제를 해보자.

  • 데이타 클래스는 뒤에 VO나 DTO를 붙여서 클래스명을 만든다.

package test.day0415;

import java.util.Date;

//데이타 클래스: 멤버변수는 모두 private
//생성자와 setter,getter 메소드로 구성
public class BoardDTO {
  private String subject;
  private String content;
  private String writeDay;
  public BoardDTO() {
    // TODO Auto-generated constructor stub
  }

  public BoardDTO(String subject, String content, String writeDay) {
    this.subject = subject;
    this.content = content;
    this.writeDay = writeDay;
  }

  public String getSubject() {
    return subject;
  }

  public void setSubject(String subject) {
    this.subject = subject;
  }

  public String getContent() {
    return content;
  }

  public void setContent(String content) {
    this.content = content;
  }

  public String getWriteDay() {
    return writeDay;
  }

  public void setWriteDay(String writeDay) {
    this.writeDay = writeDay;
  }
}

Categories:

Updated:

Comments