~전편에 이어서~

ObjectStream을 활용해보자!

 


# 오늘의 코딩 #

[순서]

1. 먼저 내보낼 객체의 기반이 되는 'MyData' Class를 생성 (Serializable interface를 구현한 클래스) 

2. ObjectStream활용을 위한 클래스를 생성하여 write와 read method를 작성/실행해보자

 

#1. MyData Class

- 사용자 정보를 가지고 있으며 직렬화가 막혀있는 변수가 존재함

package test;

import java.io.Serializable;

/**
 * 사용자의 정보를 가진 클래스
 * @author user
 */
public class MyData implements Serializable{
		
	/**
	 * serialVersionUID : 이 클래스 파일이 JVM 외부로 빠져나갔을 때 파일을 검증하기 위한 용도의 Constant
	 * 객체가 JVM 외부로 나갔을 때 검증하기 위해서 ID를 부여함
	 * 1. 현재 JVM에서 빠져나간 객체임을 검증 가능
	 * 2. 시간에 대한 체크 가능
	 */
	private static final long serialVersionUID = -6444648902030740467L;
	private double height;
	private transient double weight; // 직렬화를 막기 위해서는 transient를 걸자 (직렬화 방지)
	private int age;
	private transient String name; // 직렬화 방지
	
	public MyData() {
	}

	public MyData(double height, double weight, int age, String name) {
		this.height = height;
		this.weight = weight;
		this.age = age;
		this.name = name;
	}

	public double getHeight() {
		return height;
	}

	public void setHeight(double height) {
		this.height = height;
	}

	public double getWeight() {
		return weight;
	}

	public void setWeight(double weight) {
		this.weight = weight;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "MyData [height=" + height + ", weight=" + weight + ", age=" + age + ", name=" + name + "]";
	}
	
}//class

 

#2. UseObjectStream Class

1) MyData Class를 활용하여 객체 내보내기/읽기 Stream을 실행하는 class

package test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
 * 객체를 직렬화하여 JVM외부로 내보내거나 읽어들이는 클래스
 */
public class UseObjectStream {

	public void writeObj(MyData md) throws IOException, NotSerializableException {
		// 1. 스트림 생성
		ObjectOutputStream oos = null;
		try {
			oos = new ObjectOutputStream(new FileOutputStream(new File("C:/Users/user/Desktop/obj.txt")));
			// 2. 객체 스트림에 기록
			oos.writeObject(md);
			// 3. 스트림의 내용 분출
			oos.flush();
		} finally {
			// 4. 연결 끊기
			if (oos != null) {
				oos.close();
			}//end if
		}//end finally
	}// writeObj

	public MyData readObj() throws IOException, ClassNotFoundException {
		MyData md = null;

		// 1. 스트림 생성
		ObjectInputStream ois = null;
		try {
			ois = new ObjectInputStream(new FileInputStream(new File("C:/Users/user/Desktop/obj.txt")));
			// 2. 스트림에서 객체 읽기
			md = (MyData) ois.readObject(); // method 반환형이 object이므로 클래스로 casting 해줘야 값을 받아올 수 있음
		} finally {
			// 3. 연결 끊기
			if (ois != null) {
				ois.close();
			} // end if
		} // end fianlly
		return md;
	}// readObj

 

2) main maethod에서 실행해보자!! writeObj를 먼저 실행하면!

	public static void main(String[] args) {

		MyData md = new MyData(180.3, 73.2, 26, "김동동");
		UseObjectStream uos = new UseObjectStream();

		try {
			uos.writeObj(md);
			System.out.println("직렬화된 객체:" + md);
		} catch (NotSerializableException nse) {
			System.out.println("객체가 직렬화되지 않습니다.");
			nse.printStackTrace();
		} catch (IOException ie) {
			System.out.println("객체를 쓰는 동안 문제 발생");
			ie.printStackTrace();
		} // end catch

	}// main

}// class

# 출력 결과 #

- JVM외부로 나간 객체의 내용 & 설정한 경로에 작성된 파일

 

 

3) readObj method도 실행해보자!

		try {
			MyData md1 = uos.readObj();
			System.out.println("역직렬화된 객체:" + md1);
		} catch (ClassNotFoundException cnfe) {
			cnfe.printStackTrace();
		} catch (IOException ie) {
			ie.printStackTrace();
		} // end catch
		
	}// main

}// class

 

# 출력 결과 #

- MyData Class에서 직렬화 방지를 위해 transient로 막아둔 변수는 null로 읽힘 

  >> 해당 변수는 JVM외부로 나가지 않았다라는 것 확인!

 

 1. Overloading(Overload) 

- method 다형성의 종류

- 하나의 클래스 안에서 같은 이름의 method를 여러 개 정의하는 것

- 생성자도 Overloading 가능

- 호출될 때 구분되도록 정의하여야 함 

- 규칙) 접근지정자&반환형 달라도 됨 / method명 같아야 함 / 매개변수 반드시 다르게 정의!

 

 2. Overriding(Override) 

- method 다형성의 종류

- 상속 관계에서 부모, 자식 클래스 간에 같은 이름의 method를 정의하는 것

- 부모 클래스에서 제공하는 기능을 덮어쓰고 자식 클래스에서 수행할 기능으로 변경하는 것

   (단, 부모 클래스의 method에서 final이 선언되어 있으면 Overriding 불가)

- 규칙) *접근지정자는 달라도 되나 반환형&method명&매개변수 반드시 같도록 정의!

           *접근지정자 정의 시, 자식 클래스의 접근지정자가 부모 클래스의 접근지정자보다 광의여야 함

            (Ex. 부모 클래스 method의 접근지정자 : protected -> 자식 클래스의 method 접근지정자 : protected/public)

 

 3. Annotation (주석 달기) 

- JDK1.5에서부터 제공하는 기능

- Compiler에게 컴파일 시에 부가적인 일을 할 수 있도록 설정하는 것 (본래의 Compiler는 문법체크의 기능만 수행함)

- 종류)

    @Override : method가 Override 되었는지 컴파일 시 체크 / method 위 정의

    @Deprecated : 비추천 method인지 체크 / method 위 정의 (Ex. date.getYear())

    @SuppressWarnings : 경고를 표시할 때 사용 / method 위, method 안에서 정의

 

 4. Abstract Class 

- 상속관계에서 부모 클래스를 작성할 때 사용하는 클래스 (상속하기 위해 만드는 클래스)

- 일반 클래스의 변수/method 외에 *abstract method(추상 메소드)가 추가됨

   *abstract method

     - 구현의 강제성이 있는 method

     - 자식 클래스에서 반드시 자신에 맞게 Override 해야 함

     - 부모 클래스에 명시된 abstract method에는 body({ })가 없으므로 업무 로직 구현 불가 

- 추상클래스는 직접 객체화 되지 않음 (자식 클래스를 통해서만 객체가 생성됨)

   > extends하더라도 자식클래스 객체명 = new 자식클래스생성자();

   > 추상클래스는 일을 하지 않는다!

- abstract class 작성법)

       접근지정자 abstract class 클래스명 [extends 부모클래스명] [implements 구현인터페이스명,,] { }

- abstract method 작성법)

       접근지정자 abstract 반환형 method명 (매개변수,,);

       *접근지정자 : public, protected만 가능

       *Overloading 가능

 


# 오늘의 코딩 #

- 추상클래스 실습!

package test;

/**
 * 부모클래스 : 상속 및 abstract <br>
 * @author user
 */
 
public abstract class AbsParents {

	public AbsParents() {
//		super(); // 모든 클래스의 생성자에는 super가 생략되어 있음. 여기서의 부모 클래스는 Object.
		System.out.println("부모클래스 생성자");
	}// AbsParents

	public void parentsMethod() {
		System.out.println("부모의 기본 method");
	}// parentsMethod

	/**
	 * 집에서 밥을 먹는 method - 자식에 의해 구현될 method<br>
	 */
	public abstract void eat(); //Overloading

	/**
	 * 밖에서 밥을 먹는 method - 자식에 의해 구현될 method<br>
	 * @param menu : 음식의 종류
	 * @param price : 음식의 가격
	 * @return
	 */
	public abstract String eat(String menu, int price); //Overloading
	
}//class

- 상속관계를 통해 자식 클래스의 생성자보다 부모 클래스의 생성자가 먼저 실행되는 것을 증명하기 위해 생성자에 println 추가

- 기본 method와 abstract method (Overload로 2개 생성)

 

package test;

/**
 * 자식클래스 : extends하고 abstract method를 구체화할 당사자
 * @author user
 */
public class AbsChild extends AbsParents {

	public AbsChild() {
		System.out.println("자식클래스 생성자");
	}// AbsChild

	/**
	 *집에서 밥 먹는 method<br>
	 */
	public void eat() { //부모 클래스의 method Override
		System.out.println("집에서 밥을 먹고 있어요");
	}// eat

	/**
	 *식당에서 외식하는 method<br>
	 */
	public String eat(String menu, int price) { //부모 클래스의 method Override
		return "식당에서 " + menu + "을(를) " + price + "원 주고 먹어요";
	}// eat
	
	public static void main(String[] args) {
		//객체화
		AbsChild ac = new AbsChild(); // 부모 생성 후 자식 생성됨
		
		//상속 및 구현된 method 사용하기
		ac.parentsMethod(); //상속. 기본 method
		ac.eat(); // Override & Overload method
		System.out.println(ac.eat("제육볶음", 8000)); // Override & Overload method
		
	}// main
}// class

- 부모 클래스에서 상속된 method & abstract mehtod를 구현하여 실행!

 

# 출력 결과 #

부모클래스 생성자
자식클래스 생성자
부모의 기본 method
집에서 밥을 먹고 있어요
식당에서 제육볶음을(를) 8000원 주고 먹어요

+ Recent posts