컬렉션 프레임워크 (Collection Framework)란?

 : 잘 정의된, 약속된 구조와 골격 , 인스턴스의 저장과 참조를 위해 잘 정의된, 클래스들의 구조 의미합니다.

 

컬렉션 프레임워크라는 이름이 사용되는 이유:

4가지의 자료형이 성격에 따라서 구현된 코드들이 자료형의 이름만 변경하더라도 수행되도록 체계화 되어 있기 때문입니다.

 

         Collect
                                     List                                      Set
ArryList LinkedList HashSet TreeSet

 

List

1. 데이터의 중복을 허용합니다. (데이터 = 인스턴스)

2. 데이터를 저장할 때 저장 순서를 유지하여 관리합니다.

3. ArryList / LinkedList List의 구조를 상속받는 구조이기 때문에 Set을 특징을 그대로 물려받습니다.

 

ArryList / LinkedList

 

공통점 :

- 데이터의 중복을 허용합니다.

- 데이터를 저장할 때 저장 순서를 유지하여 관리합니다.

 

차이점 :

 

ArryList / LinkedList 둘의 장점과 단점이 반대로 되어 있습니다.

 

○ ArrayList : 배열로 되어 있는List입니다.

 

단점 :

1. 처음에 잡은 배열의 값을 넘어가면 알아서 메모리를 늘려서 값을 저장합니다. 하지만 이 과정에서 많은 시간이 소용되기 때문에 데이터 저장이 잦은 프로젝트 안에서는 비효율 적일 수 있습니다.

2. 삭제에 기능을 구현할 때 내부의 알고리즘이 복잡하게 구현되어, 성능의 저하를 가져올 여지가 있습니다.

 

장점 :

1.인덱스를 통해서 저장되어 있는 값을 빠르게 읽어올 수 있습니다. (데이터 접근 용이함)

 

○ LinkedList

 

장점:

1.저장공간을 늘리는 과정이 간단합니다.

2.삭제 동작이 매우 간단합니다.

 

단점 :

1.저장한 데이터를 참조가 불편합니다.

 

 

1) ArrayList

ArrayList : 빈번한 참조를 할 때 사용합니다. 

public class IntroArrayList {
	public static void main(String[] args) { 
		
		Integer num1 = new Integer(10); 
		Integer num2 = new Integer(20);
		Integer num3 = new Integer(30);
		
		Integer[] num = new Integer[3];
		num[0] = new Integer(10);
		num[1] = new Integer(20);
		num[2] = new Integer(30);
		
	
		
		//5버전 이후 부터 Generic으로 사용
		ArrayList<Integer> instanceInteger  = new ArrayList<Integer>(); 
        // 저장할 set 을 Integer로 한정지었다. 
	
		// 데이터 저장
		instanceInteger.add(new Integer(10)); 
		instanceInteger.add(new Integer(20));
		instanceInteger.add(new Integer(30));
		
		// 데이터 참조 
		for(int i = 0; i < instanceInteger.size(); i++ ) {   
        //  instanceInteger.size() : 저장하고 있는 instance를 반환해준다. 
			System.out.println(instanceInteger.get(i));      
            // get을 통해서 출력 할 수 있는데 시작 숫자는 0이다. 
		}
        
        // 데이터 삭제
		
		instanceInteger.remove(2); 
        // 삭제와 동시에 안에 비여있는 공간에 뒤에 있는 내용을 땡겨준다. 

- 5 버전부터 Generic을 사용하여 자료형을 선언하도록 만들었습니다.

 

- 데이터 저장을 저장할 때. add를 통해서 값을 저장합니다.

ex) instanceInteger.add(new Integer(10)); -> instanceInteger.add(10); 생략해줘도 5 버전 이후 지원해주는 AutoBoxing/ AutoUnBoxing에 의해서 오류가 나지 않습니다.

 

- 저장된 데이터를 출력할 때. get(); 사용합니다.

 

- 저장된 데이터의 개수를 확인할 때. size(); 사용합니다. (length와 같은 기능)

 

- 저장된 데이터 삭제. remove(); 삭제된 빈 공간에 뒤의 값이 들어와 하나씩 당겨줍니다.

 

 

2) LinkedList

LinkedList: 빈번하게 추가 삭제를 할 때 사용한다. 

public class IntroLinkedList {
	public static void main(String[] args) { 
		
		Integer num1 = new Integer(10); 
		Integer num2 = new Integer(20);
		Integer num3 = new Integer(30);
		
		Integer[] num = new Integer[3];
		num[0] = new Integer(10);
		num[1] = new Integer(20);
		num[2] = new Integer(30);
		
		LinkedList<Integer> instanceInteger  = new LinkedList<Integer>(); 
	
		// 데이터 저장
		instanceInteger.add(new Integer(10)); 
		instanceInteger.add(new Integer(20));
		instanceInteger.add(new Integer(30));
		
		// 데이터 참조 
		for(int i = 0; i < instanceInteger.size(); i++ ) {  
			System.out.println(instanceInteger.get(i));      
		}
        
        // 데이터 삭제
		instanceInteger.remove(2); 

위의 ArrayList와 똑같은 코드에 자료형만 바꾼 코드입니다. error가 하나도 발생하지 않으면 똑같이 진행됩니다. 이것을 보고 완벽한 호환이라고 이야기하며, 컬렉션 프레임워크 ( Collection Framework ) 임을 명확하게 보여줍니다.

 

 

Set

  1. 데이터의 중복을 허용하지 않습니다. (데이터 = 인스턴스)

  2. 데이터를 저장할 때 저장 순서를 유지하여 관리하지 않습니다.

  3. HashSet / TreeSet Set의 구조를 상속받는 구조이기 때문에 Set을 특징을 그대로 물려받습니다.

- 저장할 때

1. 중복확인을 위해서 전체 검색합니다.

2. 순서를 유지하지 않고 정리합니다.

 

: 추가적인 기능을 수행하기 때문에 퍼포먼스가 떨어집니다.

 

● HashSet / TreeSet

 

공통점 :

- 데이터의 중복을 허용하지 않습니다.

- 데이터를 저장할 때 저장 순서를 유지하여 관리하지 않습니다.

 

 차이점:

- TreeSet : 정렬해서 보관합니다. (성능이 4가지 중 가장 좋지 않다.)

- HashSet : : 정렬까지는 하지 않게 보관하며, TreeSet 성능이 더 좋아서 비교적 더 많이 사용합니다.

 

3) HashSet

 

public class IntroHashSet { 
	public static void main(String[] args) {
		HashSet<String> set = new HashSet<String>();
		
		// 데이터 저장
		set.add("Frist"); 
		set.add("Second");
		set.add("Third");
		set.add("Fourth");
		set.add("Second"); 
		
		System.out.println(set.size()); // 개수 : 4 (중복 저장x)
		
		// 데이터 참조 
		Iterator<String> itr = set.iterator();  
        // iterator(); interface로 저장되어 있다. 
        //set에 담겨 있는 정보로 itr 을 반환해 주고 있는 것이다. 
		// emthod가 스스로 new 해준다. (ex = calendar) 
		
		while(itr.hasNext()){  
    		System.out.println(itr.next());	 
		} // hasNext(): 데이터가 있는지 확인 하고 있으면 true, 없으면 false 
          // 데이터의 위치까지 확인할 수 있다. 
          // next() 사용하여 읽어 온다.
		
		// 5번전 부터 제공되는 for : each 문으로 Iterator를 사용하는 것보다 
        // 간편하게 출력할 수 있게 제공해준다. 
		for(String e:set) { 
			System.out.println(e);
		}


// 데이터 참조
for(int i = 0; i < set.size(); i++ ) {
System.out.println(set.get(i));

error : 읽어오는 get() 을 지원해 주지 않습니다 list 는 저장한 순서대로 반환 하기 때문에 의미가 있지만 set은 저장한 순서를 유지 하지 않으므로 의미가 없기 때문에 자료형의 특성상 지원해주지 않습니다. .get(); 을 대신하여 Iterator을 사용합니다.

 

Iterator란?

- iterator 메소드가 반환하는 참조값의 인스턴스는 Iterator 인터페이스를 구현하고 있습니다.
- iterator 메소드가 반환한 참조 값의 인스턴스를 이용하면, 컬렉션 인스턴스에 저장된 인스턴스의 순차적 접근이 가능

  합니다.
- iterator 메소드의 반환형이 Iterator이니, 반환된 참조 값을 이용해서 Iterator에 선언된 함수들만 호출하면 됩니다.

 

 

HashSet 저장되기 이전에 검색이 되어지는데 검색은 Object 안에 equals method를 불러와서 검색합니다.  equals method는 참조변수의 주소값으로 같은지 다른지를 확인합니다. 하지만 set 은 검색의 기능은 중복을 확인하고 있기 성능이 좋지 않으므로 내용이 많아지면 너무 늦어 질 수 있어서 이를 해결하기 위한 알고리즘을 만들어서 문제를 해결해야한다. 이를 해결하기 위해서 hashcode와 equals를 override 해서 해시알고리즘을 만들어서 보다 적은 단계로 비교하도록 만들 수 있습니다. 다음 예시를 보여드리겠습니다.

 

예시)

class Num{
	int num;
		
	Num(int num){
		this.num = num;
	}

	@Override
	public String toString() { 
		return String.valueOf(num); 
        // valueOf(num); 입력되는 데이터를 큰 따옴표를 붙여서 문자화 해준다. 
	}

	@Override
	public int hashCode() {
		System.out.println("hashCode() 호출.");
		return num % 3; 
        // 3으로 나눠서 나온 값 (0,1,2) = 각각의 결과 값끼리만 비교되도록 만든다. 
	}

	@Override
	public boolean equals(Object obj) { 
		System.out.println("equals() 호출.");
		Num comp = (Num)obj;
		
		if(comp.num == num) {
			return true;
		}else {return false;}
	}	
}

public class HashSetEquals {
	public static void main(String[] args) {
		HashSet<Num> set = new HashSet<>(); 
        
		set.add(new Num(10));
		set.add(new Num(20));
		set.add(new Num(10));
		set.add(new Num(30));

- toString 을 overriding 하여 Num 에 넣는 값을 문자화 하여 그 값을 비교하도록 합니다.

 

- hashcode 를 overriding 하여 3으로 나눠서 같은 나머지를 가진 결과들끼리 비교하도록 합니다.

 

- equals 를 overriding 하여 입력된 값과 들어오는 값을 비교하도록 합니다.

 

 

4) TreeSet

class Person implements Comparable<Person>{ 
	String name; 
	int age;
	
	Person(String name, int age){
		this.name = name;
		this.age = age;
	}
	
	public void showData() {
		System.out.println("이름 : " + name);
		System.out.println("나이 : " + age);
	}

	@Override
	public int compareTo(Person o) {
		return  o.age- age;
		
	}
}
public class ComparablePerson {
	public static void main(String[] args) {
		TreeSet<Person> set = new TreeSet<Person>();
		
		set.add(new Person("홍길동", 21));
		set.add(new Person("이순신", 25));
		set.add(new Person("강감찬", 28));
		set.add(new Person("유관순", 23));
		set.add(new Person("안중근", 25));
		set.add(new Person("강감찬", 28));
		
		for(Person e :  set) {   
			e.showData();
		}

  implements Comparable<Person> Comarable을 받아서 compareTo를 ovrriding 받아 정렬할 기준을 명확하게 해줍니다. hash code와 equals method를 사용하지 않아도 정렬하면서 필터링을 하기 때문에 필요하지 않습니다.

 

HashMap <K, V> (keyword, value)

 

- 키(key)와 값(value)의 쌍으로 구성되는 요소를 다루는 컬렉션입니다.

- K는 키로 사용할 요소의 타입, V값으로 사용할 요소의 타입 지정합니다.

- 키와 값이 한 쌍으로 삽입합니다.

- 키는 해시맵에 삽입되는 위치 결정에 사용합니다.

- 값을 검색하기 위해서는 반드시 키 이용합니다.

 

public class IntroHashMap {
	public static void main(String[] args) {
		HashMap <String, String> map = new HashMap <String, String>();
		
        // 데이터 입력 (.put();)
		map.put("이름", "홍길동"); 
		map.put("주소", "서울시 종로구");  
		map.put("이메일", "abc@aaa.com"); 
		map.put("전화번호", "010-1111-1111"); 
		
		// 데이터 참조( get(); )
		System.out.println(map.get("이름"));   
		System.out.println(map.get("주소")); 
		System.out.println(map.get("이메일")); 
		System.out.println(map.get("전화번호")); 
		
		// 데이터 삭제 
		map.remove("주소"); // key 값을 이용해서 삭제. 
		
	    System.out.println(map.get("주소"));  // 주소 값이 삭제 되어 초기값인 null 출력 

 - add를 사용하지 않고  put을 사용하는 이유는 관리의 방법이 다르기 때문입니다 : .put(); data 저장.

 

- 직접적으로 어떤 data가 들어가있는지 직관적으로 볼 수 있어서 활발히 활용합니다.

 

map 의 데이터 오름차순, 내림차순으로 출력 )

public class IntroTreeMap {
	public static void main(String[] args) {
		TreeMap<Integer, String> map = new TreeMap<Integer, String> (); 
		
		// 데이터 저장
	    map.put(6, "data6");   
	    map.put(4, "data4");
	    map.put(5, "data5");
	    map.put(2, "data2");
	    map.put(1, "data1");
	    map.put(3, "data3");
	    // map.put(new Integer(6), "data6");  
        // 5버전 부터 AutoBoxing 에 의해서 편리한 형태로 사용 가능 
        
	    for(int i = 0; i <=6 ;i++) {
	    System.out.println(map.get(i));
	    }
	    
	    NavigableSet<Integer> navi = map.navigableKeySet();

	    // 데이터 출력
	    System.out.println("==== 오름차순 =====");
	    Iterator<Integer> itr =navi.iterator();  // 
	    
	    while(itr.hasNext()) {
	    	System.out.println(map.get(itr.next()));
	    }
	    
	    System.out.println("==== 내림차순 ====");
	    itr = navi.descendingIterator();
	    
	    while(itr.hasNext()) {
	    	System.out.println(map.get(itr.next()));	
	    }

 

 직접적으로 어떤 data가 들어가있는지 직관적으로 볼 수 있어서 활발히 활용된다.

 

'빅데이터 > JAVA' 카테고리의 다른 글

[JAVA] 스트림(Stream)  (0) 2020.05.20
[JAVA] Thread  (0) 2020.05.19
[JAVA] Generics  (0) 2020.05.17
[JAVA] Calendar 클래스, Date 클래스 , Random 클래스  (0) 2020.05.17
[JAVA] Wrapper 클래스  (0) 2020.05.17

제네릭(Generics)이란?

: 특정 타입만 다루지 않고, 여러 종류의 타입으로 변신할 수 있도록 클래스나 메소드를 일반화시키는 기법입니다.

 

 

재네릭의 장점

1. 타입 안정성을 제공해줍니다.

2. 타입체크와 형변환을 생략할 수 있으므로 코드가 간결해 집니다.

 

 

- Generics 사용하기 이전에 범용적으로 사용할 수 있는 변수로 Object를 배웠습니다. Object여러 참조자료형을 사용해보도록 하겠습니다.

 

- 자료형

class FruitBox {
	Object item;
public void store(Object item)  
	{this.item =  item;}
public Object pullOut() 
    {return item;}
}

class Apple {
	int weight; // 사과의 무게
	Apple(int weight)
	    {this.weight = weight;}
	public void showAppleWeight() 
	    {System.out.println("사과의 무게 : " + weight);}
}

class Orange {
	int sugarContent; // 당분 함량
	Orange(int sugarContent)
	    {this.sugarContent= sugarContent;}
	public void  showSugarContent() 
	    {System.out.println("당분 함량 : " + sugarContent);}
}

 

public class ObjectBaseFruitBox {

	public static void main(String[] args) {
		Orange orange = new Orange(10);
		Apple apple = new Apple(500);

		FruitBox orangeBox = new FruitBox();
		orangeBox.store(orange);
		
		
		FruitBox appleBox = new FruitBox();
		appleBox .store(apple);
		
		// 1) Object 자료형을 (Apple)강제 변환
		Object orangeda = orangeBox.pullOut();
		((Orange) orangeda).showSugarContent();
		
		Object appleda= appleBox . pullOut() ;
		((Apple)appleda).showAppleWeight();
		
		
		// 2) 초기화 할때의 값을 Orange로 강제 변환해서 자장
		Orange tmpOrange = (Orange)orangeBox.pullOut();
		tmpOrange.showSugarContent();
		
		Apple tmpApple = (Apple)appleBox.pullOut();
		tmpApple.showAppleWeight();
		
		FruitBox objectBox = new FruitBox();
		
		objectBox.store("사과"); 

위의 참조자료형들을 Object를 이용하여 강제형변환을 사용하여 원하는 값을 출력할 수 있었습니다. 하지만 여기에 문제 점이 있습니다. 그것은 범용적으로 만드는 것은 좋았는데 잘못된 값을 입력하여도 error 나지 않는다는 문제점이 존재합니다. (범용적인 사용할 수 있지만 자료형에 있어서는 안전하지 않습니다.)


이러한 범용적으로 사용하면서 안정성까지 가질 수 있는 방법 = generics!

 

 Generics

: 하나의 자료형으로 범용적으로 사용고 싶을 때: new 선언시에 자료형을 결정하도록 하여 안정성을 확보합니다.  

 

class FruitBox <T>{
	T item;
public void store(T item)  
	{this.item =  item;}
public T pullOut() 
    {return item;}
}

class Apple {
	int weight; // 사과의 무게
	Apple(int weight)
	    {this.weight = weight;}
	public void showAppleWeight() 
	    {System.out.println("사과의 무게 : " + weight);}
}

class Orange {
	int sugarContent; // 당분 함량
	Orange(int sugarContent)
	    {this.sugarContent= sugarContent;}
	public void  showSugarContent() 
	    {System.out.println("당분 함량 : " + sugarContent);}
}

위의 참조자료형 정의된 것들중에서 Class FruitBox 에 Object 자리에  < T > 를 넣어서 T에 해당하는 자료형의 이름은 인스턴스를 생성하는 순간에 결정되게 합니다.

 

public class GenericBaseFruiBox {
	public static void main(String[] args) {
    
	    FruitBox<Apple> appleBox = new FruitBox<Apple> ();   
		// new 했을 떄, <T> 로 지정되었던 것이 <Apple>으로 대입해서 사용됩니다. 
		// 자료형의 type 이 apple로 고정됩니다. 
				
		Apple apple = new Apple(700);
		appleBox. store(apple);
	    // appleBox.store("사과")); // error : 자료형이 안정적으로 사용될 수 있게 되었다.  
				
		Apple tmpApple = appleBox.pullOut();
		tmpApple. showAppleWeight();
				
		FruitBox<Orange> OrangeBox = new FruitBox<Orange> ();
		Orange orange = new Orange (7);
		
        OrangeBox.store(orange);
		// OrangeBox.store(apple); //자료형이 잘못입력되어 error 
				 
	    Orange tmpOrange = OrangeBox.pullOut();
		tmpOrange.showSugarContent();
	}
}

< T > 의 자리에 참조변수 이름을 넣어서 인스턴스 생성시 결정된 T의 자료형에 일치 하지 않으면 컴파일 에러가 발생하므로 자료형에 안정적인 구조가 됩니다.

 

Generics을 통해서 코드 편의성과 자료형의 안정성 모두가 가능해졌습니다.

 

Generics method )

: 클래스의 메소드만 부분적으로 제네릭화 할 수 있습니다.

class FatherClass{
	@Override
	public String toString() {
	return "classs FatherClass"; }
}

class ChildClass{
	@Override
	public String toString() {
	return "classs ChildClass"; }
}

class InstanceTypeShower {
	int showCnt; 
	InstanceTypeShower(){
	showCnt = 0;}
	
	// GenericsMethod (자료형 1개)
	public <T>void showInstType2(T inst1) {  // 호출하는 순간 자료형으로 대신하겟다. 
		showCnt++;
		System.out.println(inst1);
	}
	
            // GenericsMethod (자료형 2개)
	public <T,U>void showInstType1(T inst1, U inst2) {  // 호출하는 순간 자료형으로 대신하겟다. 
		showCnt++;
		System.out.println(inst1);
		System.out.println(inst2);
	}
	public void showPrintCnt() {
		System.out.println("showCnt = " + showCnt);
	}
}

 

- 제네릭 메소드의 호출과정에서 전달되는 인자를 통해서 제네릭 자료형을 결정할 수 있으므로 자료형의 표현은 생략 가능 합니다.

public class IntroGenericMethod {
	public static void main(String[] args) {
		
		FatherClass father = new FatherClass();
		ChildClass child = new ChildClass();
		
		InstanceTypeShower shower = new InstanceTypeShower();
		
		shower.<FatherClass>showInstType2(father);
		shower.showInstType2(father); // <FatherClass> 생략 가능
		// shower.<FatherClass>showInstType(child); // error
		
		shower.<ChildClass>showInstType2(child);
		shower.showInstType2(child);
		
		// 2개 이상의 자료형 사용이 가능하다. 
		shower.<FatherClass,ChildClass>showInstType1(father, child);
		
		shower.showPrintCnt();
	}
}

 

매개변수의 자료형 제한)

package Generics;

interface SimpleInterface{ 
	public void showYourName();
}

class UpperClass{
	public void showYourAncestor() {
		System.out.println("UpperClass");
	}
}

class AAA extends UpperClass implements SimpleInterface{  
// 2개의 Method를 가지고 있다. 
	@Override
	public void showYourName() {
		System.out.println("Class AAA");
	}
}

class BBB implements SimpleInterface{  
	@Override
	public void showYourName() {
		System.out.println("Class BBB");
	}
}

public class BoundedTypeparam {
	public static void main(String[] args) {
		AAA aaa = new AAA();
		BBB bbb = new BBB();
		
		showInstanceAncestor(aaa); 
        // aaa 는 SimpleInterface를 구현하고 있기 때문에 문제 없다. 
		showInstanceAncestor(bbb); 
        // bbb 는 SimpleInterface를 구현하고 있기 때문에 문제 없다. 
		
		showInstanceName(aaa);
		//showInstanceName(bbb); // error extends UpperClass 하지 않기 때문이다. 
		
	}
	
	public static <T extends SimpleInterface> void showInstanceAncestor(T param) {
	// SimpleInterface 는 interface 는 implement를 사용해서 구현해야하지만 	
	// Generics 에서 상속의 개념을 넣을 때는 interface와 상속하는 class  모두 extends 사용한다. 
		
		param.showYourName();
	}
	
	public static <T extends UpperClass> void showInstanceName(T param) {
		param.showYourAncestor();	
	}
}

 

public static <T extends SimpleInterface> void showInstanceAncestor(T param) {}

 extends SimpleInterface의 자녀 class로 상속하고 있는 자료형만 가능합니다.

 

public static <T extends UpperClass> void showInstanceName(T param) {}

extends UpperClass의 자녀 class로 상속하고 있는 자료형만 가능합니다.

 

상속의 관계를 이용하여 매개변수의 자료형의 제한을 넣는 것이 가능합니다.

 

 

제네릭 메소드와 배열 )

public class IntroGenericArray {
	public static void main(String[] args) {
		String[] stArr = {"HI.", "I ' m so happy." , "JAva Generic Program."};
		showArrayData(stArr);
	}
	
	//public static <T>void showArrayData(T arr) {} 
    T 어떤 자료형이든 상관 없이 입력되는 순간 자료형으로 확정되므로  error가 나타난다. 
	
    public static <T>void showArrayData(T[] arr) {  
    // 입력 받는 참조자료형이 배열이 확신할 때, 배열 형으로 넣어 준다.                                                
		for(int i = 0; i <arr.length; i++) {
			System.out.println(arr[i]);
		}
	}
}

 

 

기본 자료형의 이름은 제네릭에 사용 불가합니다.  Wrapper 클래스를 사용하여 제네릭을 이용할 수 있습니다.

 

 

'빅데이터 > JAVA' 카테고리의 다른 글

[JAVA] Thread  (0) 2020.05.19
[JAVA] 컬렉션 프레임워크 ( Collection Framework )  (0) 2020.05.18
[JAVA] Calendar 클래스, Date 클래스 , Random 클래스  (0) 2020.05.17
[JAVA] Wrapper 클래스  (0) 2020.05.17
[JAVA] Object 클래스  (0) 2020.05.17

Calendar 클래스

: 날짜를 읽어오는 클래스입니다. Calendar는 추상 클래스 이기 때문에 직접 객체를 생성할 수 없고, 메서드를 통해서 완전히 구현된 클래스의 인스턴스를 얻어야 합니다.

 

Calendar today = new Calendar(); error!! 추상클래스는 인스턴스를 생성할 수 없습니다. 

Calendar today = Calendar.getInstance();

.getInstance() 메서드는 Calendar 클래스를 구현한 클래스의 인스턴스를 반환해줍니다.

 

추가적으로 설명을하면, 인스턴스를 직접 생성해서 사용하지 않고 이처럼 메서드를 통해서 인스턴스를 반환하게 하는 이유는 최소한의 변경으로 프로그램이 작동할 수 있도록 하기 위한 것입니다.

 

 

● 현재 날짜, 시간, 년, 월, 일, 시, 분, 초 구하기

	         // 현재 날짜 / 시간 
		Calendar today = Calendar.getInstance();
		
		// 년, 월, 일 구하기 
		int year = today.get(Calendar.YEAR); // 해당연도 return (get 의 반황형은 int)
		int month = today.get(Calendar.MONTH)+1; // 월의 정보는 1월일 때는 0의 값으로 반환한다. 
		                                         // 사용함에 있어서 +1을 해줘야한다.
                                                  
		int day = today.get(Calendar.DAY_OF_MONTH);
		System.out.printf("%d년 %d월 %d일 \n" , year, month, day);
		
		
		// 시, 분, 초 구하기 
		int hour = today.get(Calendar.HOUR_OF_DAY); // HOUR_OF_DAY(0~23시) vs  HOUR(0~12시)
		int minute = today.get(Calendar.MINUTE);
		int second = today.get(Calendar.SECOND);
		
		System.out.printf("%d:%d:%d \n",hour,minute,second);

 

현재 날짜 및 시간 : Calendar.getInstance();

 

년, 월, 일 구하기 : today.get(Calendar.DAY_OF_MONTH);

 

시, 분, 초 구하기 : 시 - Calendar.HOUR_OF_DAY , 분 - Calendar.MINUTE , 초 - Calendar.SECOND

 

 

● 요일구하기 

String[] DAY_OF_WEEK = {"일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일"};  
// 숫자로 반환 할때 일 - 0, 월 - 1 

System.out.println("오늘은 " + DAY_OF_WEEK[today.get(Calendar.DAY_OF_WEEK)-1]+ " 입니다."); 

인덱스는 0부터 시작하기 때문에 -1을 해줘야지 정확한 요일이 출력됩니다. 대괄호 안에는 인덱스, 메서드, 연산식 등 최종의 값이 0이상 인덱스의 결과값이 온다면 어떠한 문법구문도 사용 가능합니다.

 

 

 

Date 클래스

Date now = new Date();
System.out.println("현재시간 " +now.toString()); 
//.toString()을 override 하여 결과값을 나타낸다: Thu May 14 10:20:38 KST 2020

 

●Date와 Calendar 간의 변환

 

Calendar가 새로 추가되면 Date 는 대부분의 메서드가 'deprecated' 되었으므로 잘 사용되지 않습니다, 그럼에도 불구하고 여전히 Date를 필요로 하는 메서들이 존재하기 때문에 Date와 Calendar 또는 그 반대로 변화할 일이 생기게 됩니다.

 

// Calendar -> Date 변환.
Date d1 = new Date(today.getTimeInMillis());  
// 입력으로 아무것도 넣지 않으면 컴퓨터 운영체제로 가서 시간을 읽어온다. 
	    
// today.getTimeInMillis() =/ Date(long date) 
내가 처리한 임의의 시간으로 부터 출력 되게 할 수 있다. 
	    
	    
// Date -> Calendar 변환. 
Date d2 = new Date();
Calendar cal =  Calendar.getInstance() ;
	
cal.setTime(d2); 
		

 

● SimpleDateFormat

: date와 calendat만으로 날짜 데이터를 원하는 형태로 다양하게 출력하는 것은 불편하고 복잡하여 그것은 간단하게 해결할 수 있게 해줍니다.

 

 SimpleDateFormat sdf = new SimpleDateFormat("yyyy년 MM월 dd일 HH:mm:ss a"); 
 // 년 , 월 , 일 , 시, 분, 초, 오전/오후

출력값 : 2020년 5월 17일 

 

 

 

Random 클래스 

: random 으로 결과의 값을 출력하게 해줍니다.

 

추가적인 설명을 하자면 컴퓨터 안에서 규칙성 없이 출력값을 가져온다는 것이 불가능 하기 때문에 컴퓨터의 현재 시간을 Millissecond 단위로 정수화 해서 계산 한것을 return 하기 때문에 (1/1000  초) 불규칙적으로 출력되는 것으로 보이는 것입니다.

 

예시)

package exam09;

import java.util.Random;

public class RandomNumberGenerator02 {
	public static void main(String[] args) {
		Random random = new Random();
		
		
		//1~100사이의 임의의 값
		random.nextInt(100); // 0~99까지의 정수가 출력. 
		int num = random.nextInt(100)+1;
		System.out.println(num);

 

정수 뿐 아니라 소수 및 boolean 값도 출력 가능합니다.

float f = random.nextFloat(); // default 일때 0.0~1.0 사이의 임의의 실수 값 : 
System.out.println("default 일때 0.0~1.0 사이의 임의의 실수 값 : " + f);
		
boolean b = random.nextBoolean();
System.out.println("임의의 논리 값 : " + b);

 

'빅데이터 > JAVA' 카테고리의 다른 글

[JAVA] 컬렉션 프레임워크 ( Collection Framework )  (0) 2020.05.18
[JAVA] Generics  (0) 2020.05.17
[JAVA] Wrapper 클래스  (0) 2020.05.17
[JAVA] Object 클래스  (0) 2020.05.17
[JAVA] 예외처리  (0) 2020.05.15

Wrapper 클래스란?

:자바 기본 타입(자료형)을 클래스화시키는 것입니다. 쉽게 이야기해서 기본 자료형을 class를 입혀서 참조변수 처럼 사용할 수 있게 말하는 것을 의미합니다.

 

- 원칙적으로 보면 int, String와 같은 기본자료형으로 Object 를 상속 받지 않으므로 error 를 내야하지만 기본 자료형을 Object에 입력으로 전달하고 싶을 때 wrapper로 사용하면 error 없이 편리하게 사용할 수 있습니다.

 

 

 

기본 타입 값으로 Wrapper 객체 생성

Integer i = new Integer(10);
Character c = new Character(‘c’);
Double f = new Double(3.14);
Boolean b = new Boolean(true);

 

박싱(boxing)

: 기본 타입의 값을 Wrapper 객체로 변환합니다.

 

언박싱(unboxing)

: Wrapper 객체에 들어 있는 기본 타입의 값을 빼냅니다.

 

 

package exam06;

public class BoxingUnBoxing {
	public static void main(String[] args) {
	// Wrpper class : 기본 자료형을 class 로 감싸서 참조 자료형으로 사용 할 수 있도록 한다. 
	
		
		Integer iValue = new Integer(10); // Boxing 
		Double dValue = new Double(3.14); // Boxing
		
		int num = iValue.intValue(); // UnBoxing 
		// intValue : int 자료형의 담긴 값을 기본 자료형으로 반환한다. 	
		System.out.println(num);
		
		double num2 = dValue.doubleValue();// UnBoxing 
		// doubleValue : double 자료형의 담긴 값을 기본 자료형으로 반환한다.
		System.out.println(num2);

		
		iValue = new Integer(iValue.intValue()+10); 
		System.out.println(iValue.intValue());
	}

}

 

문자열을 기본 데이터 타입으로 변환

int i = Integer.parseInt("123"); 		// i = 123
boolean b = Boolean.parseBoolean("true"); 	// b = true
double f = Double.parseDouble("3.14" ); 	// d = 3.14

 

● Auto Boxing & Auto Unboxing (자바제공 Wrapper 클래스를 사용하는 것이 좋은 이유)

 

Auto Boxing : 기본 자료형 데이터가 자동으로 Wrapper 인스턴스로 감쌉니다.

Auto UnBoxing : Wrapper 인스턴스에 저장된 데이터가 자동으로 꺼내집니다.

package exam07;

public class AutoBoxingAutoUnboxing2 {
	public static void main(String[] args) {
		
		Integer num1 = 10; // AutoBoxing 에 의해서  기본 자료형 처럼 사용. 
		Integer num2 = 20;
		
		num1++;   // AutoUnBoxing // num1 = num1.intValue() + 1; (원래 이렇게 구현했어야 했다.)
		System.out.println(num1);
		
		num2 += 3;// AutoUnBoxing  // num2 = num2.intValue() + 3; (원래 이렇게 구현했어야 했다.) 
		System.out.println(num2);
		
		int addResult = num1 + num2; // int addResult = num1.intValue() + num2.intValue();
	    System.out.println(addResult);

	}

}

 

'빅데이터 > JAVA' 카테고리의 다른 글

[JAVA] Generics  (0) 2020.05.17
[JAVA] Calendar 클래스, Date 클래스 , Random 클래스  (0) 2020.05.17
[JAVA] Object 클래스  (0) 2020.05.17
[JAVA] 예외처리  (0) 2020.05.15
[JAVA] Abstract 클래스, Interface  (0) 2020.05.13

Object 클래스 

 

- java.lang 패키지에 포함합니다.

- 모든 클래스의 수퍼 클래스 입니다.

- 모든 클래스에 강제 상속합니다.

- 모든 객체가 공통으로 가지는 객체의 속성을 나타내는 메소드 보유하고 있습니다.

 

 

예시)

class Point {
	int x, y;
	public Point(int x, int y) {
		this.x = x;
		this.y = y;
	}
}
public class ObjectPropertyEx {
	public static void print(Object obj) {
		System.out.println(obj.getClass().getName()); // 클래스 이름
		System.out.println(obj.hashCode()); // 해시 코드 값
		System.out.println(obj.toString()); // 객체를 문자열로 만들어 출력
		System.out.println(obj); // 객체 출력
	}
	public static void main(String [] args) {
		Point p = new Point(2,3);
		print(p);
	}
}

출력값:
Point
366712642
Point@15db9742
Point@15db9742

 

 

 

● String toString()

: 객체를 문자열로 변환하며 , Object 클래스에 구현된 toString()이 반환하는 문자열 입니다.

class Point {
	int x, y;
	public Point(int x, int y) {
		this.x = x;
		this.y = y;
	}
	public String toString() {
		return "Point(" + x + "," + y + ")";
	}
}
public class ToStringEx {
	public static void main(String [] args) {
		Point p = new Point(2,3);
		System.out.println(p.toString());
		System.out.println(p); // p는 p.toString()으로 자동 변환
		System.out.println(p + "입니다."); // p.toString() + "입니다"로 자동 변환
	}
}

결과값 :

Point(2,3)

Point(2,3)

Point(2,3)입니다.

 

Point 클래스에 Point 객체를 문자열로 리턴하는 toString() 메소드를 작성하였습니다.

p.toString(); 과 p(); 이 동일하게 출력됩니다. (Point 객체를 문자열로 리턴하는 toString() 작성)

 

 

 

● finalize 메소드 

: 인스턴스가 완전히 소멸되기 직전 호출되는 메소드로서, Object 클래스의 멤버이므로 모든 인스턴스에는 이 메소드가 존재합니다.

 

finalize : heap에 담긴 인스턴스를 소멸하기 직전에 호출되는 명령어입니다.  마지막으로 구현하고 싶은 기능을 사용하고 인스턴스가 소멸되는데 java가 자동으로 finalize 를 호출하는 그 메서드를 override 해서 마지막 기능을 수행합니다.

 

package Object_Class.exam01;

class MyName /*extends Object*/{
String name; 
	
	MyName(String name){ 
		this.name = name;
	}

	@Override
	protected void finalize() throws Throwable { 
		super.finalize();
		System.out.println(name + "이/가 소멸되었습니다.");
	}

위의 코드를 소스코드로 활용하여 아래의  Main method에 fianlize method 를 실행 보겟습니다.

 

package Object_Class.exam01;

public class ObjectFinalize {
	public static void main(String[] args) {
		
		  System.out.println("프로그램 시작.");
		    
		    MyName obj1 = new MyName("인스턴스1");
		   
		    obj1 = null;
            
		    System.gc(); 
            // garbage collection 
            - interupt할 시간이 되지 않았더라도 소멸할 인스턴스가 있는지 찾으러 갑니다. 
		    
		    /*
		     출력 값:
		     프로그램 시작.
		     프로그램 종료. 
		     인스턴스1이/가 소멸되었습니다. 
		     
		    System.runFinalization(); 
            먼저 프로그램이 종료 되지 않고 finalize가 수행되도록 한다. 
		    
		    /*
		    프로그램 시작.
		    인스턴스1이/가 소멸되었습니다.
		    프로그램 종료.
		    */

		    System.out.println("프로그램 종료.");
	}
}

 

 

프로그램은 순차적으로 진행되는데 주기적으로 참조 변수들을 관찰하여 참조변수에 null 값이 수행된 것이 있는지 확인합니다.  인스턴스를 바라보는 참조 변수가 여러개가 있는지 일정시간 동안 확인을 하고 확실해지면 소멸시키게 됩니다.

그렇기 때문에 System.gc(); 결과 값이 다르게 나올 수 있습니다.

System.runFinalization(); 을 사용하여 먼저 프로그램이 종료 되지 않고 finalize 가 수행되도록 합니다.

 

 


● equals method

: java에서 인스턴스간의 내용비교를 목적으로 만들어놓은 메소드로,  Object 클래스에 equals 메소드를 정의해 놓았습니다.

 

 

 

● clone method

: Object 클래스에 인스턴스의 복를 목적으로 만들어놓은 메소드로, 이 메소드는 Cloneable 인터페이스를 구현하는 클래스의 인스터스에서만 호출이 될 수 있습니다.

package Object_Class.exam03;

class Point  implements Cloneable{
	private int xPos;
	private int yPos;
	
	Point(int x, int y){
		
		this.xPos = x;
		this.yPos = y;
		
	}
	
	public void showPosition(){
		System.out.printf("( %d , %d )\n", xPos, yPos);
	}

	@Override
	protected Object clone() throws CloneNotSupportedException { // 모든 자료형들이 복사 될 수 있기 떄문에 최상위 부모 class 인 Object 로 관리하도록 범용적으로 만들기 위해서 자료형이 Object 이다. 
		return super.clone();
		// return super.clone(); heap 영역에 복사해서 만들어둔 clone 내용의 주소값이 return 된다.  
		
	}


}

 CloneNotSupportedException 예외에 대한 처리할 수 있는 try / catch 문으로 감싸줘야지 수행할 수 있습니다.
복사 하기 위해서는 허락을 받아야 하는데, 허용한다는 의미로 class Point implements Cloneable 넣어줍니다.  

= Cloneable 는 이름만 가진 interface 입니다.

package Object_Class.exam03;

public class ObjectClone {

	public static void main(String[] args) {
		Point org = new Point(3,5);
		Point copy = null;
		
		System.out.println(org);
		// 출력 값 : exam04.Point@15db9742 
        // (해시코드: 일련번호)toString method 에 의해서 출력된 값. 
        
		try {
			copy =  (Point)org.clone();
		    org.showPosition();
		    copy.showPosition();
		 
		} catch (CloneNotSupportedException e) {
			System.out.println("예외 발생");
		}

	}

}

org 가 implements Cloneable 되어있으면 true 값으로 복사가 되고, 그렇지 않으면 clone 으로 부터 예외를 발생시키도록 되어 있습니다. 이는 보안을 확실하게 하기 위함입니다.

여기서 clone의 반환형이 Object이므로 최종적으로 Object 가 반환되지만 강제형변환을 통해서 참조변수에 담도록 해줍니다.

 

 

 

 // org 가 implements Cloneabl 되어 있으면 true 값으로 복사가 되고, 그렇지 않으면 clone으로 부터 예외를 발생시키도록 되어 있다.(보안을 확실하게 하기 위함이다.)
  } // 반환형은 Object 이므로 최종적으로 Object가 반환되지만 강제형변환 하여 참조변수에 담아준다.
// CloneNotSupportedException 예외에 대한 처리할 수 있는 try / catch 문으로 감싸줘야지 수행할 수 있다.
    // clone 은 인스터스에 대한 복사를 한다. (Point)
 // 복사 하기 위해서는 허락을 받아야 하는데, 허용한다는 의미로 class Point implements Cloneable 넣어준다.  = Cloneable 는 이름만 가진 interface 이다.
 // 다른 method이 들어 있지 않은 interface  표시용으로 사용(이름만 가지고 있는 interface)

 

org 가 implements Cloneabl 되어 있으면 true 값으로 복사가 되고, 그렇지 않으면 clone으로 부터 예외를 발생시키도록 되어 있다.(보안을 확실하게 하기 위함이다.)
    // org 가 implements Cloneabl 되어 있으면 true 값으로 복사가 되고, 그렇지 않으면 clone으로 부터 예외를 발생시키도록 되어 있다.(보안을 확실하게 하기 위함이다.)
  } // 반환형은 Object 이므로 최종적으로 Object가 반환되지만 강제형변환 하여 참조변수에 담아준다.
    // org 가 implements Cloneabl 되어 있으면 true 값으로 복사가 되고, 그렇지 않으면 clone으로 부터 예외를 발생시키도록 되어 있다.(보안을 확실하게 하기 위함이다.)
  } // 반환형은 Object 이므로 최종적으로 Object가 반환되지만 강제형변환 하여 참조변수에 담아준다.

 

지금까지 예외처리를 하기위해서 사용했던 것으로는 조건문(if, switch)등을 통해서 예외를 처리했습니다. 이러한 조건을 통한 예외 말고도 예외라는 말은 다른 뜻으로 사용합니다.

 

그것은 사용자(개발자)의 잘못된 조작이나 잘못된 코딩으로 인해 발생하는 프로그램 오류를 예외(exception)라고 사용합니다.

 

그렇다면 지금까지 사용했던 예외 처리인 if 문을 잠깐 보고 추가 적인 예외 문들을 보도록 하겠습니다.

 

● if문을 이용한 예외처리

 

- 나눗셈

package 예외처리;
import java.util.Scanner;
public class 예외처리{
	public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
	 	
		System.out.print("피제수 입력 : "); 
		int num1 = input.nextInt();
		
		System.out.println("제수 입력 : ");
		int num2 = input.nextInt();
		
		if(num2 ==0) { // 예외처리 & 기능의 조건 체크 
			System.out.println("0으로 나눌 수 없습니다.");
			return;
		}
	}
}

이것이 지금까지 우리가 사용해 온 예외의 처리방식입니다. if 문이 프로그램의 주 흐름인지, 아니면 예외의 처리인지 구분이 되지 않는다는 단점이 있습니다.

 

● try ~ catch 문

 

위의 같은 예제를 통해서 try ~ catch 문을 보여드리겠습니다.

 

- try : 예외발생의 감지 대상을 감싸는 목적으로 사용합니다. (예외발생 가능 지역 확인)

- catch : 발생한 예외상황의 처리를 위한 목적으로 사용합니다. (예외처리 코드 확인)

package 예외처리;
import java.util.Scanner;
public class 예외처리 {
	public static void main(String[] args) {
		
        System.out.println("두 개의 정수를 입력 : ");
		Scanner input = new Scanner(System.in);
		
		int num1 = input.nextInt();
		int num2 = input.nextInt();
		
		// 예외나 error 처리하는 명령어- try{}catch(){}
		
		// ArithmeticException
		try {
			System.out.println(num1/num2);
		}catch(ArithmeticException e){ 0으로 나누었을 때, ArithmeticException발생하는 예외.
			System.out.println("0으로 나눌 수 없습니다.");
		}
		System.out.println("프로그램 종료...");
	}
}

 num1/num2 연산이 될 때 num2 의 값이 0이 들어오게되면 :

catch로 가서 ArithmeticException의 예외가 발생하여 System.out.println("0으로 나눌 수 없습니다."); 값을 출력합니다.

여기서  ArithmeticException 0으로 나누었을 때 console 에서 나타나는 error와 함께 나타나는 예외 문구 입니다.

 

try ~ catch 의 특징 중 하나는 try문 내에서 예외상황이 발생하고 처리된 다음에는, 나머지 try문을 건너뛰고, try~catch의 이후를 실행합니다. java가 적절하게 블록을 구성해줍니다.

 

 ○ e.getMessage( ) , catch 여러개 사용 가능

getMessage : 메소드는 예외가 발생한 원인정보를 문자열의 형태로 반환해줍니다.

catch는 예외의 한개 외에도 있을 수 있을 때, 여러개를 사용할 수 있다. 

 

package 예외처리;
import java.util.Scanner;
public class ExceptionOtherTryCatch {
	public static void main(String[] args) {
		
		Scanner input = new Scanner(System.in);
		int[] arr = new int[5]; 
		for(int i = 0; i <2 ; i++)
			
		try {
			System.out.println("피제수 입력: ");
			int num1 = input.nextInt();
			
			System.out.println("제수 이력: ");
			int num2 = input.nextInt();
			
			System.out.print("연산 결과를 저장할 배열의 인덱스(0~4) 입력 : ");
			int index = input.nextInt();
			
			arr[index] =  num1 / num2;
			
		// 예외가 나눗셈 이외의 것도 있을 수 있을 때, 여러개를 사용할 수 있다. 
		}catch(ArithmeticException e) {
			System.out.println(e.getMessage());
			System.out.println("0으로 나눌 수 없습니다.");
		}catch(ArrayIndexOutOfBoundsException e) {
			System.out.println(e.getMessage());
			System.out.println("배열의 인덱스 접근 에러 발생.");
		}

ArithmeticException 의 ArithmeticExceptione.getMessage() / by zero가 출력 됩니다.

 

이 외에도 java가 정의 하고 있는 예외처리

// ArrayIndexOutOfBoundsException
try {
int[] arr = new int[3];
arr[-1] =20; // index 값은 0부터 시작. // ArrayIndexOutOfBoundsException 배열의 범위를 넘어설때 나타나는 예외
}catch(ArrayIndexOutOfBoundsException e) {
System.out.println(e.getMessage()); // getMessage : java 가 사용하는 오류 메세지 출력
System.out.println("배열의 범위를 벗어남."); 
}	
			
				
// ClassCastException
try {
Object obj = new int[10];  // 모든 자료형은 java가 Object를 상속하는 구조로 만들어주기 때문에 
// 다형성에 관계에 의해서 자식의 자료형을 부모의 자료형으로 바라 볼 수 있으므로 문제 없다.
String Str = (String) obj;    // int 형을 String으로 잘못된 강제 형변환에 의한 error 발생 
}catch(ClassCastException e) { // ClassCastException: 강제형변환 예외.
System.out.println(e.getMessage()); // getMessage : java 가 사용하는 오류 메세지 출력
System.out.println("int 형을 String으로 잘못된 강제 형변환에 의한 error 발생 "); 
}

// NegativeArraySizeException
try {
Object obj = new int[-10]; 
}catch(NegativeArraySizeException e) { 
System.out.println(e.getMessage()); // getMessage : java 가 사용하는 오류 메세지 출력 //
} // null 출력 , 모든 결과가 메세지로 나오지 않는다. 
				
				
// NullPointerException
try {
String name = null;
int length = name.length(); 
// NullPointerException : 참조자료형에 new 의해서 주소값을 담아주지 않고 
   method를 생성하기 때문에 발생. 주소값이 담겨 있지 않는 null 값이다. // name 값이 null
}catch(NullPointerException e) {  
System.out.println(e.getMessage());
}

 

 

java는 문법적으로나 수학적으로 문제가 일어났을 때에만 예외처리 할 수 있습니다. 그렇다면 문법적으로는 문제는 없지만 논리적으로나 물리적으로 문제가 되는 경우는 ex) 나이 값을 음수로 넣었다면?? 어떻게 해야할까요?

이러한 문제점을 해결하기 위해서 프로그래머 스스로 예외상황이 발생했을 때 처리하도록 문법 구문을 제공합니다.

 

<사용자 정의 예외 처리 자료문>

class AgeInputException extends Exception{ //Exception 예외처리 기능 
	AgeInputException(){
		
		super("유효하지 않은 나이를 입력하셨습니다."); 
	}
}

public class ProgrammerDefineException {

	public static void main(String[] args) {
		System.out.println("나이를 입력하세요 : ");

		int age;
		try {
			age = -20;
			System.out.println("당신의 나이는 : " +  age + " 살 이군요.");
			
		} catch (AgeInputException e) {
			System.out.println(e.getMessage()); 
		}
	}
	

위와 같이 나이의 값에 음수를 넣게 되면 catch로 넘어가서 사용자가 정의한 class로 가서 supe()의 값을 출력합니다.

결과값 : "유효하지 않은 나이를 입력하셨습니다."  가 출력됩니다.

 

○ throw

 

public class ProgrammerDefineException {
	public static void main(String[] args) {
		System.out.println("나이를 입력하세요 : ");

		int age;
		try {
			age = readAge();
			System.out.println("당신의 나이는 : " +  age + " 살 이군요.");
			
		} catch (AgeInputException e) {
			//e.printStackTrace(); // printStackTrace() 의 기능 : 예외가 발생했을 때 메세지를 출력해준다. 
			System.out.println(e.getMessage()); 
		}
	}
	 public static int readAge() throws AgeInputException{ 
   -- throws AgeInputException 실행과정에서 예외가 발생할 수 있는 method 임을 명시하는 것입니다. 
		 Scanner input = new Scanner(System.in);              
   -- throws AgeInputException 가 있는 method 를 받을 때는 try catch 문으로 받아야합니다.
		 int age = input.nextInt();
		 
		 if(age < 0) 
			 AgeInputException except =  new AgeInputException(); 
			 throw except; 
   -- throws catch 문을 찾겠다. throw가 제공 되는 method가 
      나타나면 try , catch 문으로 받아야한다.
		 } 
		 return age;  
	 }
}

throw : 예외의 상황을 던져버린다. 그리고 return을 받는 main method 에서 try ~ catch 문으로 받았다.

예외가 처리되지 않고 넘어감을 명시해야 하며, 예외인스턴스의 참조변수를 기반으로 구성을 합니다.

 

Abstract class 란?

 

1. 추상 메소드를 하나라도 가진 클래스이며, 클래스 앞에 반드시 abstract라고 선언해야 합니다.

abstract class Shape { // 추상 클래스 선언
	public Shape() { }
	public void paint() { draw(); }
	abstract public void draw(); // 추상 메소드
}

 

 

2. 추상 메소드가 하나도 없지만 abstract로 선언된 클래스 입니다.

abstract class MyComponent { // 추상 클래스 선언
	String name;
	public void load(String name) {
		this.name = name;
	}
}

 

그렇다면 추상 메소드(abstract method)란 무엇일까요?

public abstract String getName();
public abstract void setName(String s);

- 선언되어 있으나 구현되어 있지 않은 메소드 : abstract로 선언 합니다.

- 추상 메소드는 서브 클래스에서 오버라이딩하여 구현해야 합니다.

- 상속 관계하에 다형성에 의한 method overriding 하는 method 입니다.
- 기능을 재정의! 순수하게 overriding 되어 기능을 업그레이드 하기 위합입니다.  
- 이름만 빌려주는 것으로 자녀 class에서 기능을 재정의 해서 사용합니다 (불완전한, 완전하지 않은 method)

 

abstract class Friend  
{         
       ……         
       public void showData()         
       {             
           System.out.println("이름 : "+name);             
           System.out.println("전화 : "+phoneNum);             
           System.out.println("주소 : "+addr);         
           }        
           public abstract void showBasicInfo(); // 메소드를 완성시키지 않는다는 선언 
           } 

- showBasicInfo 메소드는 비어있습니다. 이렇듯 오버라이딩의 관계유지를 목적으로 하는 메소드는 abstract로 선언이

  가능합니다.
- 하나 이상 abstarct 메소드를 포함하는 클래스는 abstract로 선언되어야 하며, 인스턴스 생성은 불가합니다.
- 인스턴스 생성은 불가능하나, 참조 변수 선언 가능하고, 오버라이딩의 원리 그대로 적용합니다.

 

● 추상 클래스의 상속 2 가지 경우

 

1. 추상 클래스의 단순 상속

- 추상 클래스를 상속받아, 추상 메소드를 구현하지 않으면 추상 클래스 됩니다.

- 서브 클래스도 abstract로 선언해야 합니다.

 

2. 추상 클래스 구현 상속

- 서브 클래스에서 슈퍼 클래스의 추상 메소드 구현(오버라이딩)해야합니다.

- 서브 클래스는 추상 클래스 아닙니다.

 

 

Line, Rect, Circle 은 추상클래스 Shape를 상속받아 만든 서브 클래스로서, draw()를 오버라이딩 하고 있는 것입니다.

그러므로 Line, Rect, Circle 은 추상 클래슥 아니며 이들은 인스턴스를 생성할 수 있습니다.

 

 

 Interface 란?  

: 인터페이스는 두 결과물의 연결고리가 되는 일종의 약속 역할한다고 이야기 할 수 있습니다.

 

● 인터페이스(interface)의 특징

 

1. 모든 메소드가 추상 메소드

2. 상수와 추상 메소드로만 구성

3. 필드(멤버 변수) 선언 불가

4. 인터페이스 선언 (interface 키워드로 선언)

5. 모든 메소드는 abstract public이며 생략 가능

6. 상수는 public static final 타입이며 생략 가능

7. 다른 인터페이스 상속 가능

8. 인터페이스의 다중 상속 가능

 

 

인터페이스의 목적

: 인터페이스는 스펙을 주어 클래스들이 그 기능을 서로 다르게 구현할 수 있도록 하는 클래스의 규격 선언이며,

  클래스의 다형성을 실현하는 도구로서 사용하는 것입니다.

 

 

 

● 인터페이스 활용

interface AIInterface {
	void recognizeSpeech(); // 음성 인식
	void synthesizeSpeech(); // 음성 합성
}

class AIPhone implements AIInterface { // 인터페이스 구현

	// AIInterface의 모든 메소드를 구현한다.
	public void recognizeSpeech() { ... } // 음성 인식
	public void synthesizeSpeech() { ... } // 음성 합성

	// 추가적으로 다른 메소드를 작성할 수 있다.
	public int touch() { ... }
}

 

인터페이스는 둘 이상을 동시에 구현 가능하며,  인터페이스의 상속(구현)은 extends가 아닌 implements를 사용합니다.

 

 

추상 클래스와 인터페이스 비교

 

유사점

- 객체를 생성할 수 없고, 상속을 위한 슈퍼 클래스로만 사용합니다.

- 클래스의 다형성을 실현하기 위한 목적으로 사용합니다.

 

다른점

 

'빅데이터 > JAVA' 카테고리의 다른 글

[JAVA] Object 클래스  (0) 2020.05.17
[JAVA] 예외처리  (0) 2020.05.15
[JAVA] 메서드 오버라이딩(Method Overriding) , Instanceof연산자  (0) 2020.05.07
[JAVA] 상속(inheritance)  (0) 2020.05.05
[JAVA] 콘솔 출력  (0) 2020.05.04

메서드 오버라이딩(Method Overriding)이란?

: 부모 클래스 메소드의 이름, 매개변수 타입 및 개수, 리턴 타입 등 모든 것 동일하게 작성하는 것입니다. 쉽게 말해서 메소드 무시하기, 덮어쓰기로도 이야기 할 수 있습니다.

 

오버라이딩(Overriding)

 

- 오버라딩의 조건상속 관계라는 전제하에 상위 클래스에 정의된 메소드의 이름, 반환형, 매개 변수 선언까지 완전히

  동일한 메소드를 하위 클래스에서 다시 정의합니다.

 

- 부모 클래스에 선언된 메소드를, 각 자식 클래스들이 자신만의 내용으로 새로 구현하는 기능 입니다.

 

- 상속을 통해 '하나의 인터페이스(같은 이름)에 서로 다른 내용 구현'이라는 객체 지향의 다형성 실현합니다.

 

- 다형성 : 다형성이란 같은 자료형에 여러 가지 객체를 대입하여 다양한 결과를 얻어내는 성질을 의미합니다.

   - 다형성의 효과 : 하나의 타입으로 다양한 결과를 얻을 수 있고, 객체를 부품화하여 유지 보수를 용이하게 합니다.

 

오버라이딩과 비슷한 단어의 오버로딩이라고 있습니다. 그 둘은 명확히 다른 예약어 이므로 혼동되면 안됩니다.

그 둘을 비교해보겠습니다.

 

 

● 오버라이딩 관계에서의 메소드 호출 

package 상속;

class AAA {
public void rideMethod(){
System.out.println("AAA's Method");
} // overriding (가려짐)
public void loadMethod(){
System.out.println("void Method");
} // overloading
} 

class BBB extends AAA { 
public void rideMethod(){
System.out.println("BBB's Method");
} // overriding (가려짐)
                   public void loadMethod(int num){
                   System.out.println("int Method");
                   } //overloading
} 
class CCC extends BBB {
public void rideMethod(){
System.out.println("CCC's Method");
} // overriding 
                   public void loadMethod(double num){
                   System.out.println("double Method");
                   } // overloading
}

public class RideAndLoad {
	public static void main(String[] args) {
		        // 다형성 관계 
				AAA ref1 = new CCC();  
				BBB ref2 = new CCC(); 
				CCC ref3 = new CCC(); 
				 
				// method overriding 
				ref1.rideMethod(); // CCC's Method        
				ref2.rideMethod(); // CCC's Method       
				ref3.rideMethod(); // CCC's Method  
				
 rideMethod(); 다형성의 overriding 되어 있으므로, 
 CCC 자료형의 overriding 되어 있는 rideMethod();로 실행한다. 
                
				// method overloading
				ref3.loadMethod(); // void Method - AAA
				ref3.loadMethod(1); // int Method - BBB
				ref3.loadMethod(1.2); // double Method - CCC
		
	}

}

 메서드 rideMethod();가 ref1~ref3 까지 상속 관계로 정의된 메소드의 이름, 반환형, 매개 변수 선언까지 완전히 동일한 메소드가 정의 되어있기 때문에 rideMethod(); 의 결과 값은 ref1과 ref2이 가리워져서 ref3.rideMethod();의 값으로 출력됩니다.

 

 

instanceof 연산자와 객체의 타입 판단

: 레퍼런스가 가리키는 객체의 타입 식별을 위해 사용합니다 또한 상속 안에서만 의미를 가집니다.

 

- 형태 : 참조변수 instanceof 자료형 

- 결과값 :  boolean 값 (true = 참조변수가 자료형을 안다, false = 참조변수가 자료형을 모른다.)

 

● instanceof 연산자 사용예시

class Person { }
class Student extends Person { }
class Researcher extends Person { }
class Professor extends Researcher { }

public class InstanceOfEx {
	static void print(Person p) {
		if(p instanceof Person)
			System.out.print("Person ");
		if(p instanceof Student)
			System.out.print("Student ");
		if(p instanceof Researcher)
			System.out.print("Researcher ");
		if(p instanceof Professor)
			System.out.print("Professor ");
		System.out.println();
	}
	public static void main(String[] args) {
		System.out.print("new Student() ->\t"); print(new Student());
		System.out.print("new Researcher() ->\t"); print(new Researcher());
		System.out.print("new Professor() ->\t"); print(new Professor());
	}
}

new Student() -> Person Student

new Researcher() -> Person Researcher

new Professor() -> Person Researcher Professor -- new Professor() 객체는 Person 타입이기도 하고, Researcher, Professor 타입이기도 합니다.

 

 

주의) instanceof 가장 하단의 자식 class 부터 역순으로 비교하도록 해야지 원하는 자료형을 찾아볼 수 있습니다.

 

'빅데이터 > JAVA' 카테고리의 다른 글

[JAVA] 예외처리  (0) 2020.05.15
[JAVA] Abstract 클래스, Interface  (0) 2020.05.13
[JAVA] 상속(inheritance)  (0) 2020.05.05
[JAVA] 콘솔 출력  (0) 2020.05.04
[JAVA] 배열 (array)  (0) 2020.05.02

+ Recent posts