공부복습_2주차

전재우·2021년 1월 31일
2

상속

  • class B가 다른 class A의 모든 멤버 변수와 메소드를 그대로 받으면 B가 A를 상속받는다라고 한다. A - B (부모 -자식 관계)
  • 하나의 부모는 여러 자식을 가질 수 있고 부모는 또다른 자식이 될 수도 있다.
  • 어떤 Class가 아무런 상속을 받지 않은 경우 java.lang.Object class가 그 Class의 부모가 됩니다.
  • electronic ← mobile ← Phone
  • 상속 관계에 있는 자식 타입의 객체를 생성하면 메모리에 부모 객체가 먼저 생성된다
  • 부모와 자식 관계에서도 int 와 double과 같이 대소가 존재한다 →상속 관계에서는 부모가 더 크다.
  • 즉 참조 범위는 부모가 자식보다 높고 할당되는 메모리는 자식이 부모보다 크다

java Code로 상속관계를 표현 할때는 extends 키워드를 사용합니다.

자바는 단일 상속만 가능 → 한개의 클래스만 extends 가능하다.

다중 상속대신에 자바는 인터페이스를 사용하여 여러 메소드를 구현 할 수 있다.

public class B (object 클래스가 생략 되어 있다){  }
 

public class B extends A {         }

this.getClass().getName())
->클래스 이름을 가지고 온다.

Parent x = new Child(); //가능 -> 이렇게 선언한 경우 child이 있긴 있지만  Parent 타입만 사용한다.

Child y = new Parent(); //불가능 -> child 으로 선언한 경우 parent와  , child가 모두 필요하지만  Parent만 존재하기 때문에 사용X

default vs protected

default,pivate은 하위 클래스가 상속 받아도 접근 할수 없습니다 → 접근하기 위해서는 protected나 public 클래스를 사용 해야한다.

protected는 상속 관계 이거나 동일 패키지에서 접근 가능하다.

this는 자기자신

super는 부모 객체를 의미

부모의 멤버 변수가 private으로 되어 있다면 super에 public getter를 이용하여 접근 가능하다.

super.getName;

부모클래스에서 제공하는 생성자가 있는 경우 자식의 클래스에서 부모 클래스에 있는 생성자를 호출 가능하다

→ super(name,level) ;

자식 class의 기본 생성자는 부모 class의 생성자를 별도로 호출하지 않으면 부모 class의 기본 생성자를 호출합니다.

그런데 부모클래스의 기본 생성자가 없으면 오류가 발생합니다!

super호출자의 경우는 무조건 자식 생성자 이전에 만들어 져야한다

한 클래스 파일에 여러 클래스 등장 할 수 있지만 public이라고 수식어가 붙어 있는 클래스는 하나 밖에 없다.

→여러개의 클래스가 있을때 파일의 이름이 클래스 이름과 같은 클래스 앞에 접근지정자가 존재한다.

object Class -toString()

public static void main (string[] args) {
	Virsus virus = new Virus("UNJNOWN",5);
	System.out.println(virus);//이렇게 사용하게 되면 toString을 선언 해줬다면 선언해준것이 
//나오고 아니면 클래스와 주소가 나온다
}

다형성(Polymorphism)

Type 과 Method를 로 크게 나누어 생각 할 수 있다. (Overridng과 객체 reference 타입으로 다형성을 만들 수 있다)

  • Method Overloding과 Overriding으로 다형성 구현

  • Overloading

    name이 같아도 Parameter가 다르면 별개의 메소드로 간주 → 생성자() {} , 생성자 (String name){} 두개 다른것

  • Overriding ****중요 → 재정의

    상속관계에서 부모 Class의 method를 자식 Class에서 재정의 할 수 있음

    상속관계에서 부모의 Class method를 파라미터를 다르게 만들면 오버로딩 이다.

Type

부모 type으로 자식 type의 객체를 reference 할 수 있습니다

즉 한개의 type으로 여러 하위 type의 객체를 할당 받을 수 있다.

Object←Phone ← FolderblePhone

Object o = new Object;
Object o = new Phone;
Object o = new FoldeblePhone;
Virus corona = new Corona("Covid19", 8 ,20); //Virus <- corona //Virus 호출 범위

		coroan.toString();//호출 가능
		corona.showInfo(); //호출 불가

Virus 호출 범위 ,new Corona -호출 대상

하위 클래스(corona)에서 재정의 한 메소드만 사용 가능하다 .

→ 재정의 (overriding) 된 Method만 부모 type으로 선언한 변수로 호출하면 호출이 된다.

public class OverridingABCDE {
	public static void main(String[] args) {
		//AA x = new CC(); x.a();
		//CC x = new EE(); x.b(3);
		//DD x = new BB(); x.b();
		//BB x = new DD(); x.a();
	}
}

class AA{
	void a(int i) { System.out.println("AA:a(int i)"); }
}

class BB extends AA{
	void b() { System.out.println("BB:b()"); }
}

class CC extends BB{
	void a() { System.out.println("CC:a()"); }
	void b(int i) { System.out.println("CC:b(int i)"); }
}

class DD extends CC{
	void a(int i) { System.out.println("DD:a(int i)"); }
	void b() { System.out.println("DD:b()");}
}

class EE extends DD{
	void a() { System.out.println("EE:a()"); }
	void b() { System.out.println("EE:b()"); }
}

복습 할때 예상 해볼것! 결과 \

재정의 할 경우 계속 계속 밑에를 타고 내려간다고 생각

Override Annotation

  • Method를 재정의 할 때, @Override Annotation을 사용하기를 권장
  • Annotation은 부모 class의 특정 method를 재정의 한다고 compiler에게 명시하는것
  • 만약, 부모 class에 해당 method가 없는 경우 compile 오류가 발생한다.
  • 하지만 ,@override를 명시하지 않을경우 부모 class에서 오버라이딩한 클래스가 사라질 경우 새로운 메소드 선언으로 인식하고 오류를 표시 하지 않는다!
  • 재정의 된 메소드는 method name, return type, parameter - 부모와 동일 해야한다
  • 단, 접근 지정자는 부모의 접근지정자보다 범위가 크거나 같은것만 가능하다 → 즉 부모가 default면 protected, public 가능 → private 불가능
@Override //Annotation
	void getName() {
		// TODO Auto-generated method stub
		System.out.println("name : Tomson");
	}

Interface*

  • 추상화의 꽃!
  • 클래스 안의 메소드가 추상 메소드인 미완성의 클래스( java-8 구상 메소드 제외)
  • 단일 상속을 선택한 java는 Operation(method)의 추상화를 class와 독립적인 개념으로 Interface라고 이름짓고
  • 한 Class가 여러개의 Interface를 구현(Implements) 할 수 있도록 했다.
  • Interface에는 관련된 methods 들을 기술하는데, 선언부만 기술하고 구현부는 없다.
  • 상속은 본질적으로 재사용 인데 반해, 인터페이스는 본질적으로 규약 ,약속 이다.
  • 상속을 통해서 자식 class는 부모 class의 멤버 변수와 메소드를 자동으로 받는다
  • 구현을 통해 class는 인터페이스에 있는 추상 methods 선언을 반드시 구현해야하는 의무를 가지게 됩니다.
  • 인터 페이스 안의 method의 경우 접근 지정자를 생략하면 public으로 지정됨
  • 인터페이스 안의 모든 필드는 static, final 이다!
public interface Folder{
	public void fold();
	public void open();

}

A , B 가 있을때 A가 m()이라는 메소드가 필요할떄 인터페이스 타입으로 I를 선언하고 M() 을 선언한다

그런 후에 B라는 클래스에서 인터페이스 I의 m()을 구현을 한뒤에 A()가 m()의 메소드가 필요할때 I =new B로 만들어서 B의 다른 메소드를 사용하지 않고 m()만 사용 할 수 있다.

상속은 부모클래스를 전부 이식하는반면 인터페이스는 타 클래스에서 지정한 기능만을 불러오는 역할

인터페이스는 연결해서 기능을 불러오는 역할을 합니다.

java - 8버전에는 body를 가진 method를 interface에 추가 되었다

package com.inter;

class Tom{
	int age = 50;
}
interface Hillary{
	int age = 46; //인터페이스 안의 필드는 static, final이 default이다.
}

class Bill{}

public class LittleTom extends Tom implements Hillary {
	int age = 20;
	public void test() {
		System.out.println(age); //littleTom
		System.out.println(this.age); //littleTom
		System.out.println(super.age); //tom
		System.out.println(Hillary.age); //Hillary
	}

추상클래스 (abstract)

  • 추상 메소드 : 함수의 body({}) 부분이 없는 미완성의 함수
  • 추상 클래스 : 추상 메소드를 가지는 클래스
public abstract void go(String m);//메소드

public abstract class myAbstract{
	public abstract void go(String m); //클래스
}

추상 class는 class이나 추상 method를 가져 , 스스로 객체를 만들지 못합니다. → new 사용 불가

다른 클래스에서 추상클래스를 상송해서 미완성의 메소드를 구현해 줘야함

추상 method 앞에 abstract keyword를 붙인다.

class는 추상 class의 method를 구현할 의무를 가진다

public class Complete extends Myabstract{
	public void go (String m) {} // 이정도만 해도 완성 된것!
}

추상클래스를 상속받아도 상속과 똑같은 취급 → circle은 shape 타입

추상 클래스를 이용한 type 상속! 가능

Shape[] s = new Shape[3]; //3칸짜리 배열이 만들어진것 -> shape가 만들어 진것이 아님 -> shape 타입의 데이터만 들어감
		
		
		s[0] = new Circle(10);
		s[1] = new Rect(3 ,5);
		s[2] = new Circle(15);

추상 클래스 VS 인터페이스

  • 인터페이스와 추상 클래스 모두 자식에게 타입만 물려준다!
  • 인터페이스안에 들어 있는 추상 메소드와 추상 클래스의 추상 메소드와의 차이점
  • 인터페이스 → 다른 클래스에서 미완성의 메소드를 구현해 줘야함 (implements) class대 interface는 상속
  • 추상클래스 → 다른 클래스에서 미완성의 메소드를 구현해 줘야함 (extends) class 대 class는 상속!
  • 인터페이스를 implements 해도 상속관계가 존재한다고 본다.
  • (extends) student → bill← (implements)member이면 bill은 student타입이고 또 member 타입이다.
  • 인터페이스 간에도 상속 가능 하다.

instanceof

folder f = new folderble Phone()일때

상속이거나 implement 인것을 나타내는 연산자

Folder f = new FolderblePhone();
		
		if( f instanceof Folder ){ //F= reference ,Folder =클래스 이름 
			System.out.println("instanceof Folder");
		}
		
		if( f instanceof Object ){
			System.out.println("instanceof Object");
		}
		
		if( f instanceof Phone ){
			System.out.println("instanceof Phone");
		}

⇒ f라는 reference가 가리키는 대상이 Folder 인가요 라고 묻는것

아래와 같은 결과 발생

instanceof Folder
instanceof Object
instanceof Phone

IOC ioc = new IOC();
		
		if( ioc instanceof IOA ) {
			System.out.println("IOA");
		}else if( ioc instanceof IOB ) {
			System.out.println("IOB");
		}else if( ioc instanceof IOC ) {
			System.out.println("IOC");
		}
		
			if( ioc instanceof IOC ) {
				System.out.println("IOC");
			}else if( ioc instanceof IOB ) {
				System.out.println("IOB");
			}else if( ioc instanceof IOA ) {
				System.out.println("IOA");
			}
	}

}

instanceof 연산자를 사용할때는 제일 하위클래스 부터 올라와야한다.

Inner Class

클래스 안에서 다시 정의 되는 class를 말한다.

원래 클래스 안에 다른 클래스를 선언 할수 없다 → top level class는 불가능

→ 이너 클래스는 toplevel 클래스 안에 들어 있는것 이기 때문에 가능하다.

  • anonymous Class

    class안에서 이름이 없이 만들어지는 Inner Class, 이름이 없으므로 재사용되지 않고 한번 사용되고 ,한번 사용한다는건 ,객체를 생성하는 코드에 바로 class의 내용을 전달.

    new Folder 다음에 정의된 내용은 인터페이스 객체가 아니라 인터페이스를 구현한 어떤 익명 클래스 객체

    package com.inner;
    
    abstract class Movie{
    	abstract void play();
    }
    interface Game{
    	 void play(); //public abstract 
    }
    
    class MyMovie extends Movie{
    
    	@Override
    	void play() {
    		// TODO Auto-generated method stub
    		
    	}
    	
    }
    public class MP3Player {
    	public void start(Movie m) {
    		m.play();
    	}
    	public void start(Game g) {
    		g.play();
    	}
    	
    	public static void main(String[] args) {
    		MP3Player player = new MP3Player();
    		//무명클래스 : 클래스 선언과 생성을 동시에 수행하는 클래스 . 1회용
    		player.start(new Movie() {
    
    			@Override
    			void play() {
    				// TODO Auto-generated method stub
    				System.out.println("harry potter");
    			}// movie클래스를 상속 받는 자식을 선언 후 생성까지 함
    			
    		});
    		player.start(new Movie() {
    
    			@Override
    			void play() {
    				// TODO Auto-generated method stub
    				System.out.println("kim");
    			}
    			
    			
    			
    			
    			
    		});
    		
    		player.start {
    			
    			public void play() {
    				System.out.println("king kong");
    			}
    		
    		
    			
    		});
    	}
    }
  • member Class
    member Class : 바깥쪽 객체가 먼저 생성된 후에 사용 가능 하다.

자동차가 만들어 져 있지 않으면 엔진 혼자 생성 불가능 으로 쉽게 이해해보자.

package com.inner;

public class Car {
	int num = 1234;
	//member inner class 
	public class Engine{
		public void go() {
			System.out.println(num);
		}
	}
	public static void main(String[] args) {
		Car c = new Car();
		System.out.println(c.num);
		**Engine e = c.new Engine();**
		e.go();
		System.out.println(e.getClass().getName());
	}
}
  • local Class

  • static Class

    Static Class : 객체 생성을 하지 않고 사용 할 수 있는 이너 클래스

    package com.inner;
    //inner Class
    public class Outer {// top - level class
    	
    	static int count = 99;
    	
    	//static inner class
    	
    	static class Inner{
    		public void go() {
    			System.out.println(count);
    		}
    	}
    	
    	public static void main(String[] args) {
    		System.out.println(Outer.count);
    		Outer.Inner i = new Inner();
    		i.go();
    		System.out.println(i.getClass().getName());
    	}
    }

    밑줄친 부분이 anonymous를 사용하는 방법

static Class

객체를 생성하지 않고 사용하기 위해 선언하는 클래스

→ Math.PI

Final Class

더이상 자식 class를 만들지 않을려면 final keyword를 사용

//order 4번가지 하기

pay 메소드에서 trash를 사용하지 않으려고 money와 watch를 그룹을 묶어주는게 필요할때

valuable로 implements해서 pay 메소드에 valuable로 파라미터를 받게 되면 trash를 거를 수 있다.

만약에 다른 사용자가 서비스를 제공받고자 할때는 인터페이스만 주어서 사용할 메소드를 알게 해주면된다.

인터페이스 안에는 abc만 들어 있을때 다른 클래스에서는 go(){} 메소드를 알지도 못하고 사용도 못한다 .

사용할때는 싱글톤 패턴으로 인터페이스를 선언하고 인스턴스를 불러온다 static 은 어디서든 접근 가능하다.

IBookManager bookManager = IBookManagerImpl.getInstance();

OOP 응용

  • <> GENERIC

    한 컨테이너에 여러 타입을 삽일 할 수 있다

    대부분의 소스들은 컴파일에서 타입이 다 정해지지만

    Generic 타입은 컴파일이 끝나도 generic의 타입이 정해져 있지 않고 실행될때 type이 정해진다.

    public static void main(String[] args) {
    		GenericTest<String> t1 = new GenericTest<>(); //이떄 타입이 정해진다.
    		GenericTest<Integer> t2 = new GenericTest<>(); // integer 은 기본형이였던 INT를 참조형으로 변환시킨것
    		GenericTest<Circle> t3 = new GenericTest<>(); //추상클래스  Circle 타입	
    }
    public class GenericContainer<T> {
        private T obj;
    
        public GenericContainer(){}
    
        public T getObj() { return obj; }
    
        public void setObj(T t) { obj = t; }
    }

JCF (java Collection Framework)

Collection

  • 여러 개의 데이터를 저장하고 관리 할 수 있는 자료구조
  • 데이터 저장 /관리 방식에 따라 list / set / map 구조로 나뉨
  • List
  • Set
  • Map
  • Queue

Iterator Interface

장점 Iterator를 사용하면 삭제를 할때 전체적인 index나 null을 신경 쓸 필요가 없어진다

→반복 도중 List에 변화에 동적으로 대응

  • Iterator Method

boolean hasNext() - 다음 인덱스에 존재하는지 묻는 메소드

next() 있는것을 호출하는 메소드

Arraylist

순서가 유지되며

일정이상의 데이터가 들어와도 알아서 배열을 늘려 준다.

ArrayList<Rect> shape =new ArrayList<>();
List<Rect> shape = new ArrayList<>();
//참조 객체를 유연하게 바꾸기 위해서 인터페이스 객체로 선언한다.

HashSet

중복이 불가능한 배열

Set<Patient> patientList = new HashSet<Patient>();
		patientList.add(p1);
		patientList.add(p2);
Patient p3 = new Patient("환자3", 33, "010-3333-3333", "고열", "001", false);
		univHospital.addPatient(p3);
		univHospital.addPatient(p3);
//p3는 여러번 등록하더라도 한번만 등록됨

HashSet은 두 객체의 중복 여부를 체크할떄 List계열보다 엄격.

Object class의 hashCode()를 이용하여 그 값이 같은 경우에 같은 객체로 인식한다.

객체가 다르면 다른 hashCode() 리턴하도록 overriding 합니다.

PriorityQueue

객체를 정렬할때 그 객체는 comparable Interface를 구현해야한다.

Comparable Interface는 compareTo()라는 우선운위 비교 Method가 있다.

Corona c1 = new Corona("Corona5", 5, 5);
		Corona c2 = new Corona("Corona7", 5, 7);
		Corona c3 = new Corona("Corona3", 5, 3);
		Corona c4 = new Corona("Corona9", 5, 9);
		Corona c5 = new Corona("Corona1", 5, 2);
		Corona c6 = new Corona("Corona1", 5, 6);
		Corona c7 = new Corona("Corona1", 5, 5);
		Corona c8 = new Corona("Corona1", 5, 8);
		Corona c9 = new Corona("Corona1", 5, 10);
		
		PriorityQueue<Corona> pq = new PriorityQueue<>();
		pq.add(c1);
		pq.add(c2);
		pq.add(c3);
		pq.add(c4);
		pq.add(c5);
		pq.add(c6);
		pq.add(c7);
		pq.add(c8);
		
		while(!pq.isEmpty()) {
			System.out.println(pq.poll());
			//하나씩 꺼내 쓰는것 
		}

comparator : sort의 두번째 인자에서 사용되는 Interface

comparable : compareTo()를 이용하기 위한 Interface /compare : 인자 2개의 order를 비교하는 함수명"로 정리해보았습니다!

anonymous 표현

Collections.sort(list, new Comparator<Virus>() {

			@Override
			public int compare(Virus o1, Virus o2) {//앞쪽에서 뒤에쪽을 빼면 내림차순
				return o1.getLevel() - o2.getLevel();
			}
			
		});

lamba 식 표현

Collections.sort(list, ( o1, o2 ) -> {

			return o1.getLevel() - o2.getLevel();
			
		});

Exception (예외처리)

프로그램 실행 중 발생하는 문제 상황

→ 데이터베이스 연결시, 파일 입/출력시, 배열의 잘못된 인덱스 접근

  • Error

    복구가 불가능한 문제 상황

    stackOverFlowError, NoSuchMethodError

  • Exception

    복구 가능한 문제 상황

    NullPointerException, IOException ,

    RuntimeException -실행 도중에 발생하는 예외

    Non-RuntimeException (예시 : InterruptedException) 실행이 안되기 때문에 무조건 예외 처리를 해줘야한다.

-RuntimeException , other Exceptions

  • RuntimeException

    런타임시 발생되므로 예측할 수 없음

    nullPointerExcetption

    버그로서 반드시 해결

-처리방법 3가지

  • try- catch-finally

    예외가 발생한 곳에서 직접 처리하는 방식

    try는 예외가 발생 할 수 있는 부분을 블럭으로 만들고

    Catch는 그 예외상황을 처리할 방법을 블럭으로 만든다

    finally는 예외 발생 여부와 관계 없이 무조건 수행되어야 하는 코드를 블럭으로 만든다/.

    FileInputStream fis = null;
    		try {
    			fis = new FileInputStream("hello.txt");			
    		}catch(FileNotFoundException e) {
    			System.out.println("Handing Exception : " + e.getMessage());
    			e.printStackTrace();
    		}finally {
    			try {
    				fis.close();
    			}catch(Exception e) {
    				e.printStackTrace();
    			}
    		}
  • throws

    직접 처리하지 않고 호출한 쪽(호출자로 ) 예외처리를 위임 넘긴다.

    public static void main(String[] args) throws FileNotFoundException {
    		// FileInputStream fins = new FileInputStream("hello.txt");
  • try catch throw

    예외처리를 직접 처리하되 새로운 예외 발생시 호출한 쪽으로 넘긴다.

    #3 throw e
    		FileInputStream fis = null;
    		try {
    			fis = new FileInputStream("hello.txt");			
    		}catch(FileNotFoundException e) {
    			System.out.println("Handing Exception : " + e.getMessage());
    			e.printStackTrace();
    			
    			throw new IOException(); // throw IOException 객체 to main()
    			
    		}finally {
    			try {
    				fis.close();
    			}catch(Exception e) {
    				e.printStackTrace();
    			}
    		}

IO 관련 class는 IO관련 예외가 자주 발생 →try-catch 구문을 자주 사용한다.

AutoCloseable Interface가 추가 되어 try() 괄호 안의 자원은 finally에서 반납할 필요 없다. (자동반납)

AutoCloseable Interface

try( FileInputStream fis  = new FileInputStream("hello.txt"); ) {
			// fis code
		}catch(IOException e) {
			System.out.println("Handing Exception : " + e.getMessage());
			e.printStackTrace();
		}
// Not Runtime Exception 
		FileInputStream fis = null;
		try {  fis = new FileInputStream("hello.txt");  }
		catch(Exception e) {
		   System.out.println("Handing Exception : " + e.getMessage()); //
		  }
		catch(IOException e) {  System.out.println("Handing Exception : " +
		  e.getMessage());  }
		catch(FileNotFoundException e) { //
		 System.out.println("Handing Exception : " + e.getMessage()); // }

Exception > IOException > FileNotFoundException 상속관계가 존재 할떄는 구체적인 case부터 catch해야한다.

-method overriding

  • method를 재정의 할 떄 , 부모 calss의 method가 throws하는 예외의 범위를 넘어 설 수 없다.

    (접근 지정자는 부모의 범위보다 넓은 경우만 사용 가능)

    예외는 작게, 접근은 넓게 //**???

  • 만약 상속 받은 메소드에 throw를 추가 하게 된다면 부모클래스도 같이 고쳐줘야한다.

JAVA IO

데이터의 시작과 끝이 있고 양쪽 사이에 데이터가 이동하는데 이때 시자과 끝을 node 나머지를 stream이라고 한다.

  • Stream

    Stream은 두가지로 나누어 생각하는데 문자Character와 비문자binary로 나누어 생각

    InputStream - 입력용 outputStream - 출력용

    입출력 단위 charater Stream (한글쓸때 charater Stream 사용), Byte Stream

    데이터입출력방법

    1. Node(sink) Stream(직접)→ 필수적으로 사용
    2. process Stream (간접) → 가공이 필요한경우 사용

//?? Object는 무엇을 나타내나나

FIle.Separator는 os에 독립적으로 사용여 코딩 할 수 있다.

String dirName = "c:"+File.separator+"SSAFY"+File.separator+"mydir";
boolean success = file1.mkdir(); //폴더 만들기 
			if( success ) {
				System.out.println("Folder Created!" );
			}
		}
		
		File file2 = new File(dirName, "test2.txt"); 
		
		//file2.createNewFile();		 //파일 만들기
		file2.delete();// 파일 삭제
	}

Buffered

IO를 할때 Buffered를 사용하게 되면 1000배 정도의 속도 차이가 난다.!

public class BufferPerformanceTest {
	public static void main(String[] args) {
		
		File src = new File("c:/Windows/explorer.exe");
		File target = new File("c:/Temp/copied_explorer.exe");
		
		try (FileInputStream fi = new FileInputStream(src); //autocloseable
			 FileOutputStream fo = new FileOutputStream(target);
			 BufferedInputStream bi = new BufferedInputStream(fi);
			 BufferedOutputStream bo = new BufferedOutputStream(fo);) {
			
			 copy("노드", fi, fo);
			 copy("보조", bi, bo);
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void copy(String type, InputStream input, OutputStream output) throws IOException {
		long start = System.nanoTime();
		byte[] cart = new byte[1024];
		int read = -1;
		while ((read = input.read(cart)) > 0) {
			output.write(cart, 0, read);
		}
		long end = System.nanoTime();
		System.out.println(type + ", 소요 시간: " + (end - start) + "ns");
	}
}

객체 직렬화

말그대로 객체를 직렬화하여 전송 가능한 형태로 만드는 것을 의미한다. 객체들의 데이터를 연속적인 데이터로 변형하여 Stream을 통해 데이터를 읽도록 해준다.

바이트 단위로 변환되어 전송되는 작업이다.

이것은 주로 객체들을 통째로 파일로 저장하거나 전송하고 싶을 때 주로 사용된다.

그럼 역직렬화(Deserialization)는?

직렬화된 파일 등을 역으로 직렬화하여 다시 객체의 형태로 만드는 것을 의미한다. 저장된 파일을 읽거나 전송된 스트림 데이터를 읽어 원래 객체의 형태로 복원한다.

전제 조건 !

직렬화를 위한 전제조건이 있다. 바로 직렬화가 가능한 클래스를 먼저 만드는 것이다.

Serializable 인터페이스를 implements 해서 직렬화가 가능한 클래스로 만든다.

숨기고 싶은 정보는

transient를 이용하여 직렬화 대상에서 제외하기

ObjectStream

import java.io.Serializable;

class Person implements Serializable {
	
	private static final long serialVersionUID = 1L;
	private String name;
	private int age;
	private transient String ssn; //숨기고 싶은 정보를 transient 추가한다.
	
	public Person(String name, int age, String ssn, String userId, String userPass) {
		this.name = name;
		this.age = age;
		this.ssn = ssn;
	}
	
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", ssn=" + ssn	+ "]";
	}
}
public class ObjectStreamTest {
	
		public static void main(String[] args) {
			File target = new File("c:" + File.separator + "SSAFY" + File.separator + "objPerson.dat");
			Person person = new Person("홍길동", 20, "111111-2222222", "hong", "1234");
			try {
				//객체 저장
//				ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(target));
//				oos.writeObject(person);
//				oos.close();
				
				// 객체 로딩
				ObjectInputStream ois = new ObjectInputStream(new FileInputStream(target));
				Object readed = ois.readObject();
				if (readed != null && readed instanceof Person) {
					Person casted = (Person) readed;
					System.out.println(casted);
				}
				ois.close();
				
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
}

객체 직렬화를 위해 Serializable interfcae를 implement해야한다.

String 개념정리

S

package com.io;

public class StringTest {

	public static void main(String[] args) {
		String s = "mylimeorange"; //스트링의 경우 두가지 모두 가능
		String t = new String("mylimeorange");//1
		String x = "mylimeorange"; //2
		
		if(s==t) //주소값 비교
			System.out.println("s == t"); //false
		
		if(s.equals(t)) //내용 비교
			System.out.println("s.equals(t)"); //true
		
		if(s==x)//주소값 비교
			System.out.println("s == x");		//true
	
		System.out.println(s);

		String b = s.concat("hello"); //concat된 s는 따로 다른공간에 저장되어 있고 s는 변화 x
		System.out.println(s);
		System.out.println(b);
		
		s = s + "gogogo"; // 이렇게 사용하게 되면 원래 저장되어있던 s gogog가 추가로 들어 오는것이 아니라 
											 //새로생긴 s로 가르키게 된다.
		System.out.println(s);
		
		StringBuilder sb = new StringBuilder("mylimeorange"); //StringBuilder는 원본이 수정 가능하다.
		sb.append("hello");
		sb.insert(2, 'q');
		System.out.println(sb);
	}

}
profile
코린이

0개의 댓글