컬렉션(collection)

- 여러 객체(데이터)를 모아 놓은 것을 의미

 

프레임웍(framework)

- 표준화, 정형화된 체계적인 프로그래밍 방식

 

컬렉션 프레임웍(collections framework)

- 컬렉션(다수의 객체)을 다루기 위한 표준화된 프로그래밍 방식

- 컬렉션을 쉽고 편리하게 다룰 수 있는 다양한 클래스를 제공

- java.util패키지에 포함. JDK1.2부터 제공

 

컬렉션 클래스(collection class)

- 다수의 데이터를 저장할 수 있는 클래스


컬렉션 프레임웍의 핵심 인터페이스

List Set Map

언터페이스 특 징
List 순서가 있는 데이터의 집합.
데이터의 중복 허용
ArrayList, LinkedList, Stack, Vector 등
Set 순서를 유지하지 않는 데이터의 집합,
데이터의 중복을 허용하지 않는다.
HashSet, TreeSet 등
Map 키(key)와 값(value)의 쌍(pair)으로
이루어진 데이터의 집합
순서는 유지되지 않으며,
키는 중복을 허용 하지 않고, 값의 중복을 허용한다.
HashMap, TreeMap, Hashtable,
Properties 등

 

ArrayList

- ArrayList는 기존의 Vector를 개선한 것으로 구현원리와 기능적으로 동일

  ArrayList와 달리 Vector는 자체적으로 동기화처리가 되어 있다.

- List인터페이스를 구현하므로, 저장순서가 유지되고 중복을 허용한다.

- 데이터의 저장공간으로 배열을 사용한다.(배열기반)

 

Collection은 인터페이스, Collections는 유틸 클래스

 

ArrayList에 저장된 객체의 삭제과정은

for(int i=0; i<list.size(); i++)
	list.remove(i);

형태로 진행하게 되면은

0일때 처음의 0을 지워주고 나머지 데이터가 올라가서 삭제가 이상하게 된다.

for(int i=list.size()-1; i>=0; i--)
	list.remove(i);

ArrayList의 저장된 마지막 객체부터 삭제하면 삭제가 잘 된다.


 

배열의 장단점

장점 : 배열은 구조가 간단하고 데이터를 읽는 데 걸리는 시간(접근 시간, access time)이 짧다.

 

단점 : 크기를 변경할 수 없다, 비순차적인 데이터의 추가,삭제에 시간이 많이 걸린다.

- 크기를 변경해야 하는 경우 새로운 배열을 생성 후 데이터를 복사해야 함

- 크기 변경을 피하기 위해 충분히 큰 배열을 생성하면, 메모리가 낭비됨.

- 데이터를 추가하거나 삭제하기 위해, 다른 데이터를 옮겨야 됨.

- 순차적인 데이터 추가와 삭제는 빠르다.

 

배열의 단점을 보완하기 위해서 나온것이 Linked List

Linked List 

- 배열과 달리 링크드 리스트는 불연속적으로 존재하는 데이터를 연결(Link)

 

컬렉션 읽기(접근시간) 추가 / 삭제 비 고
ArrayList 빠르다 느리다 순차적인 추가삭제는 더 빠름
비효율적인 메모리사용
LinkedList 느리다 빠르다 데이터가 많을수록 접근성이 떨어짐

스택과 큐 (Stack & Queue)

스택(Stack) : LIFO구조. 마지막에 저장된 것을 제일 먼저 꺼내게 된다. (밑이 막힌 상자)

큐(Queue) : FIFO구조. 제일 먼저 저장한 것을 제일 먼저 꺼내게 된다.

 

 

캡슐화

접근 제어자를 사용하는 이유?

 

- 외부로 부터 데이터를 보호하기 위해서

- 외부에는 불필요한, 내부적으로만 사용되는, 부분을 감추기 위해서

 

캡슐화를 하는 가장 큰 이유는 정보 은닉

캡슐화를 통해 외부에서 내부의 정보에 접근하거나 변경할 수 없게 직접적인 접근을 막고

객체가 제공하는 필드와 메소드를 통해서만 접근이 가능

 

정보은닉의 장점?

외부에서 특정 객체의 데이터 및 함수의 접근을 막음으로써, 유지보수나 확장시 오류의 범위를 최소화 할 수 있고,

객체내 정보손상, 오용을 방지하고, 조작법이 바뀌어도 사용방법 자체는 바뀌지 않고, 다른 객체에 영향을 주지 않기 때문에 독립성도 좋아서 객체를 모듈화 할 수 있어 새로운 시스템의 구성에 하나의 모듈처럼 사용이 가능


다형성

- 여러 가지 형태를 가질 수 있는 능력

- 조상 타입 참조 변수로 자손 타입 객체를 다루는 것

- 객체와 참조변수의 타입이 일치할 때와 일치하지 않을 때의 차이?

- 자손 타입의 참조변수로 조상 타입의 참조 변수를 가리킬 수 없다.

 

참조변수가 조상타입일 때와 자손타입일 때의 차이는 사용할 수 있는 멤버의 갯수가 달라짐


참조변수의 형변환

- 사용할 수 있는 멤버의 갯수를 조절하는 것

- 조상, 자손 관계의 참조변수는 서로 형변환 가능


instanceof 연산자

- 참조변수의 형변환 가능 여부 확인에 사용. 가능하면 true 반환

- 형변환 전에 반드시 instanceof로 확인해야 함

SinRamen sin = new SinRamen();
System.out.println(sin instanceof Object); // true
System.out.println(sin instanceof Ramen); // true
System.out.println(sin instanceof SinRamen); // true

Ramen ra = new Ramen();
System.out.println(ra instanceof SinRamen); // false

Ramen을 상속받고 있다고 가정하에 true가 나온다.

마지막은 부모가 자식이 되려고 하면 false를 반환한다.

import 문

- 클래스를 사용할 때 패키지 이름 생략할 수 있다.

- 컴파일러에게 클래스가 속한 패키지를 알려줌

 

class ImportTest {
	java.util.Date today = new java.util.Date();
}

// 대신 상단에 import 선언 후
import java.util.Date;

class ImportTest{
	Date today = new Date();
]

- java.lang 패키지의 클래스는 import하지 않고도 사용 가능

 String, Object, System, Thread ... 등등등

 

import java.lang.*; 모든 클래스(생략 가능 default package)

import문이 없으면 모든 클래스에 패키지 이름을 붙여야 함.

 

- import문은 컴파일 시에 처리되므로 프로그램의 성능에 영향 없음.

static import문

- static멤버를 사용할 때 클래스 이름을 생략할 수 있게 해준다.

import static java.lang.Integer.*;
import static java.lang.Math.random;
import static java.lang.System.out;

System.out.println(Math.random()); // 대신
out.println(random()); // 으로 생략 할 수 있게 해준다.

제어자

- 클래스와 클래스의 멤버(멤버 변수, 메서드)에 부가적인 의미를 부여한다.

 

접근 제어자 public, protected, (default), private

그         외 static, final, abstract, native, transient, synchronized, volatile, strictfp

 

- 하나의 대상에 여러 제어자를 같이 사용가능(접근 제어자는 하나만)

public class ModifyTest{
	public static final int WIDTH = 200;
    
	public static void main(String[] args){
    	System.out.println("WIDTH="+WIDTH);
    }
}

static - 클래스의, 공통적인

멤버변수에 붙으면?

- 모든 인스턴스에 공통적으로 사용되는 클래스 변수가 됨

- 클래스 변수는 인스턴스를 생성하지 않고도 사용 가능

- 클래스가 메모리에 로드될때 생성

메서드에 붙으면?

- 인스턴스를 생성하지 않고도 호출 가능한 static 메서드가 된다.

- static메서드 내에서는 인스턴스 멤버들을 직접 사용 불가능.

 

final - 마지막의, 변경될 수 없는

멤버변수(iv),지역변수(lv) 변수 앞에 final이 붙으면, 값을 변경할 수 없는 상수가 된다.

클래스 앞에 붙으면 변경될 수 없는 클래스가 된다. final로 지정된 클래스는 다른 클래스의 조상이 될 수 없음.

메서드 앞에 붙으면 변경될 수 없는 메서드, final로 지정된 메서드는 오버라이딩을 통해 재정의 될 수 없다.

 

abstract - 추상의, 미완성의

클래스 앞에 붙으면 클래스 내에 추상 메서드가 선언

메서드 앞에 선언부만 작성하고 구현부는 작성하지 않은 추상 메서드임을 알린다.

 

추상메서드를 가지고 있는 클래스를 추상 클래스 라고 함.

미완성 메서드임 선언부고 몸통(구현부)가 존재 하지 않음.


접근 제어자(access modifier)

private : 같은 클래스 내에서만 접근이 가능하다.

(default) : 같은 패키지 내에서만 접근이 가능하다.

protected : 같은 패키지 내에서, 그리고 다른 패키지의 자손클래스에서 접근이 가능하다.

public 접근 제한이 전혀 없다.

 

 

오버라이딩(overriding)

- 상속받은 조상의 메서드를 자신에 맞게 변경하는 것

- override 덮어 쓰다

 

class Ramen{
    String soup; // 라면 스프
    String noodle; // 라면의 면
    
    String getExplain(){ // 라면 설명 메서드
    	return "soup : " + soup + "noodle : " + noodle;
    }
}

class SinRamen extends Ramen{
	String stuff; // 건더기
	
    String getExplain(){ // 오버라이딩
    	return "soup : " + soup + "noodle : " + noodle + "stuff : " + stuff;
    }
}

오버라이딩의 조건

1. 선언부가 조상 클래스의 메서드와 일치해야 함

2. 접근 제어자를 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다.

3. 예외는 조상 클래스의 메서드보다 많이 선언할 수 없다


참조변수 super

- 객체 자신을 가리키는 참조변수. 인스턴스 메서드(생성자)내에만 존재

- 조상의 멤버자신의 멤버와 구별할 때 사용

 

class Parent { int x = 10; }

class Child extends Parent{
    int x = 20;
    
    void method(){
    	System.out.println("x=" + x);
    	System.out.println("this.x=" + this.x);
    	System.out.println("super.x=" + super.x);        
    }
}

출력되는 값을 예측해보면

일단 x는 Child 가까운 인스턴스 변수에 담긴 20을 가리킨다

this 또한 자기자신을 가리키는 20

super는 부모를 가리키는 10을 호출시킨다.

 

만약 Child 클래스에 int x = 20;이 없으면 조상의 10이 호출이 된다.

 

super() - 조상의 생성자

- 조상의 생성자를 호출할 때 사용

- 조상의 멤버는 조상의 생성자를 호출해서 초기화

- 생성자의 첫 줄에는 반드시 생성자를 호출해야 한다.

  그렇지 않으면 컴파일러가 생성자의 첫 줄에 super();를 삽입

 

class Ramen{
    String noodle; // 면
    
    public Ramen(String noodle){
    	this.noodle = noodle;
    }
}

class SinRamen extends Ramen{
    String stuff;
    
    public SinRamen(String noodle,String stuff){
    	this.noodle = noodle;
        this.stuff = stuff;
    }
}

패키지(package)

- 서로 관련된 클래스의 묶음

- 패키지는 소스파일의 첫 번째 문장으로 단 한번 선언

- 같은 소스 파일의 클래스들은 모두 같은 패키지에 속하게 된다

- 패키지 선언이 없으면 이름없는(unnamed) 패키지에 속함

- 클래스의 실제 이름(full name)은 패키지를 포함.(java.lang.String) rt.jar는 클래스들을 압축한 파일

rt는 runtime을 의미함.

rt.jar는 zip파일하고 비슷해서 풀 수 있음, jar.exe로 압축해제 가능

 

 

자바 프로그램이 실행될때 필요한 클래스들의 묶음을 rt.jar에서 갖고 있음.

 

클래스 패스(classpath)

- 클래스 파일(*.clas)의 위치를 알려주는 경로(path)

- 환경변수 classpath로 관리하며, 경로간의 구분자는 ';'를 사용

 classpath(환경변수)에 패키지의 루트를 등록해줘야 함.

 

JVM이 프로그램을 실행할 때, 클래스파일을 찾는 데 기준이 되는 파일 경로를 말한다.

 

상속

- 기존의 클래스로 새로운 클래스를 작성하는 것 (코드를 재사용하기 위함!)

- 두 클래스를 부모와 자식으로 관계를 맺어주는 것.

 

class 자식클래스 extends 부모클래스 {
	// ...
}

- 자손은 조상의 모든 멤버를 상속받는다. (생성자, 초기화블럭 제외)

- 자손의 멤버 개수는 조상보다 적을 수 없다.(같거나 많다)

 

확장이 되는것이므로 extends 확장되다 라는 키워드를 사용하는 것

 

class Ramen{
	String noodle;
}

class SinRamen extends Ramen{
	String soup;
}

class SinRamen{
	String noodle;
    	String soup;
}

상속을 받은 SinRamen과 3번째의 SinRamen은 같다 인스턴스 멤버 갯수는 같다.

상속을 받았기 때문에 noodle이라는 인스턴스 변수가 있기 떄문


포함(composite)이란?

- 클래스의 멤버로 참조변수를 선언하는 것

- 작은 단위의 클래스를 만들고, 이 들을 조합해서 클래스를 만든다.

 

포함관계를 들면

 

신라면이 만약 라면을 상속받고 있고,

신라면의 스프가 매운맛의 스프를 가지고 있으면, 스프는 신라면이 포함을 하고 있는 것이다.

 

신라면과 신라면 볶음이 있으면 라면은 국물이 있기 때문에 둘은 포함관계이거나 상속을 가질 수는 없다.

코드로 적어보자면

 

class Ramen{
	Soup soup = new Soup(); // 소스를 포함하고 있음
	String noodle; // 면도 밀가루 클래스로 만들 수 있지만 일단 soup로만
}

class Soup{
	String powder; // 신라면 소스 파우더
	String envelope; // 포장 용지 봉투로
}

class SinRamen extends Ramen{
	String stuff = "spicystuff"; // 매운 건더기?
}

신라면은 라면이다. 상속관계 is-a

라면은 스프를 가지고 있다. 포함관계 has-a


단일 상속(Single Inheritance)

- Java는 단일상속만을 허용한다.(C++은 다중상속 허용)

 

Object 클래스 - 모든 클래스의 조상

- 부모가 없는 클래스는 자동적으로 Object 클래스를 상속받게 된다.

- 모든 클래스는 Object 클래스에 정의된 11개의 메서드를 상속받는다.

toString(), equals(Object obj), hashCode(), ...

 

 

 

오버로딩

한 클래스 안에 같은 이름의 메서드 여러 개 정의하는 것

 

오버로딩이 성립하기 위한 조건

1. 메서드 이름이 같아야 함

2. 매개변수의 개수 또는 타입이 달라야 함

3. 반환 타입은 영향 없다

 

int add(int a, int b) { return a+b; }
int add(int x, int y) { return x+y; } // 메서드 중복 정의 

int add(int a, int b) { return a+b; }
long add(int a, int b) { return (long)(a+b); } // 메서드 중복 정의 반환타입은 영향 없음

int add(int a, long b) { return a+b; }
int add(long a, int b) { return a+b; } 타입이 다르므로 오버로딩 O

마지막 add메서드를 호출할 때, add(3,3) 하면 어떤게 long타입이고 어떤게 int 타입인지 몰라 ambiguous 에러가 발생한다.

 


생성자

- 인스턴스가 생성될 때마다 호출되는 '인스턴스 초기화 메서드'

- 인스턴스 생성시 수행할 작업(iv 초기화)에 사용

 

Time t = new Time(12, 34, 56);

조건

클래스이름 (타입 변수명,String str, ...){
	// 인스턴스 생성 시 수행될 코드
    // 주로 인스턴스 변수의 초기화 코드를 적는다.
}

클래스 이름은 생성자 이름이 들어간다.

리턴값이 없다(void 안붙임)

모든 클래스는 반드시 생성자를 가져야 한다.

컴파일러가 기본 생성자를 추가시켜준다.

기본 생성자

- 매개변수가 없는 생성자

클래스 이름() {} // 기본 생성자
Point() {} // Point클래스의 기본 생성자

매개변수가 있는 생성자는 컴파일러가 자동으로 기본 생성자를 만들어주지 않는다.

생성자가 하나도 없을 때만 컴파일러가 자동으로 추가 시켜줌.

 

매개변수가 있는 생성자

Car(String c, String g, int d) {
	color = c;
	gearType = g;
	door = d;
}

Car c = new Car("white","auto",4);

// 매개변수가 있는 생성자가 없을 시
Car c = new Car();
c.color = "white";
c.gearType = "auto";
c.door = 4;

매개변수가 없는 생성자는 여러 줄로 iv들을 초기화 시켜줘야 하는 과정이 있기 때문에

매개변수가 있는 생성자를 이용하면 더 편리하다.


생성자 this()

- 생성자에서 다른 생성자를 호출할 때 사용

class Ramen{
	String soup; // 라면 스프
	String noodle; // 면
	String ramenType; // 라면 종류
    
    Ramen(){
    	this("spicy","Thick","sinramen");
    }
    
    Ramen(String soup){
    	this(soup, "Thic","sinramen");
    }
    
    Ramen(String soup, String noodle, String ramenType){
    	this.soup = soup;
        this.noodle = noodle;
        this.ramenType = ramenType;
    }
}

this를 사용하면 같은 클래스 안에 있는 생성자 사용 가능

다른 생성자 호출 시 첫 줄 에서만 사용 가능!


참조변수 this

- 인스턴스 자신을 가리키는 참조변수

- 인스턴스 메서드(생성자 포함)에서 사용가능

- 지역변수(lv)와 인스턴스 변수(iv)를 구별할 때 사용


변수의 초기화

- 지역 변수는(lv)는 수동 초기화 해야한다.

- 멤버변수(iv, cv)는 자동 초기화 된다.

멤버 변수의 초기화 종류

1. 명시적 초기화(=)

int door = 4; // 기본형 변수 초기화

Engine e = new Engine(); // 참조형 변수 초기화

 

2. 초기화 블럭

- 인스턴스 초기화 블럭 : { }

- 클래스 초기화 블럭 : static { }

 

3. 생성자

 

초기화 순서

cv -> iv

자동 -> 간단 -> 복잡

 

 

+ Recent posts