'JAVA/JAVA'에 해당되는 글 14건

  1. 2019.04.28 [자료구조]List
  2. 2019.04.23 Garbage Collector
  3. 2019.04.22 jvm 메모리 구조
  4. 2019.02.23 [객체지향] JAVA SOLID 원칙
  5. 2017.05.17 제네릭 메소드
  6. 2017.05.16 제네릭 개념 알기
  7. 2015.08.28 다형성
  8. 2015.08.13 클라이언트 ip 구하기

[자료구조]List

JAVA/JAVA 2019. 4. 28. 16:37 |

List

리스트는 특정 타입 값들이 순차적으로 정렬된 컬렉션입니다.

LinkedList, ArrayList 클래스를 일반적으로 사용합니다.

리스트는 자바의 배열하고 다릅니다. 

리스트는 크기 지정에 한계가 없으므로 리스트를 사용하기 전에 크기를 지정할 필요가 없습니다.

 

LinkedList 와 ArrayList 가 각각 적합한 경우에 대해 알아보겠습니다.

 

배열과 리스트 차이

- 배열은 정의할 때 크기를 지정해야 함.

- 배열의 원소에 인덱스값을 지정하여 직접 접근가능(랜덤접근)

- 배열 크기를 늘려야할때 새로운 배열을 만들고 재정렬하는 절차를 가짐 

- 정수 타입 배열은 final 을 지정할 수 없음

 

 

ArrayList 

리스트의 데이터로 배열을 사용하는 List 인터페이스이다.

- ArrayList 클래스 생성시 배열의 초기 크기 지정할 수 있음 (default 10)

- 크기가 추가될때 마다 자동으로 배열을 재할당 함 (단,시간이 소요되고 메모리용량 소모함-> 큰 컬렉션을 이용할거면 미리 크기를 지정함)

- ArrayList 시작위치나 중간 위치에 값을 추가하려고 하면 모든 원소는 공간을 위해 이동해야됨 (=>크기가 크다면 연산량이 많은 작업임)

- 배열 크기 재할당은 단반향으로 이루어짐

- 원소를 줄여도 배열 크기는 줄지않음

 

 

LinkedList

연결리스트를 구현 할수 있는 또다른 리스트 구현체입니다.

원소들을 저장하는데 배열을 이용하지 않고 리스트안에서 다음 원소를 가리키는 내부 객체를 이용합니다.(노드참조값)

 

 

결론

ArrayList 순차적인 추가/삭제 유리함

인덱스를 참조하고 있어서 검색할때 LinkedList 보다 빠르다.

 

LinkedList 는 비순차적인 추가/삭제에 유리함

 

 

 

 

'JAVA > JAVA' 카테고리의 다른 글

Garbage Collector  (0) 2019.04.23
jvm 메모리 구조  (0) 2019.04.22
[객체지향] JAVA SOLID 원칙  (0) 2019.02.23
제네릭 메소드  (0) 2017.05.17
제네릭 개념 알기  (0) 2017.05.16
Posted by 양승아
:

Garbage Collector

JAVA/JAVA 2019. 4. 23. 11:26 |

Garbage Collertor 알고리즘 동작 방식 알아보자.

- Serial GC

- Parallel GC

- Parallel Old GC

- Concurrent Mark - Sweep GC

- G1 (Garbage First)GC

 

Serial GC

-XX:+UseSerialGC 

young/old 영역을  Single CPU를 사용한다.(현재 거의 사용 안함)

 

Parallel GC 

-XX:+UseParallelGC

young 영역은 멀티쓰레드로 처리되지만, Old 영역은 싱글쓰레드로 처리된다.

 

 Parallel Old GC

-XX:+UseParallelOldGC

young/old 영역 모두 멀티 쓰레드 방식으로 처리된다.

 

Concurrent Mark & Sweep GC (CMS)

-XX:+UseSerialGC

영역의 크기가 클 때 적합한 방식이다.

Suspend Time 분산하여 응답시간을 개선한다

비교적 자원이 여유있는 상태에서 GC 의 Pause Time 을 줄이는 목적으로 사용한다.

 

 

*Minor GC

eden 이 가득차면 삭제할 object들을 찾는다.(참조하지 않는 객체)

참조중 (계속 사용할 객체)면 Survior 영역으로 옮겨둠

참조가 없으면 남겨둔다(eden)

참조중인 객체가 모두 넘어가면 Eden을 싹 청소함

 

* Full GC

 old 영역: 접근 불가능 상태로 되지 않아 young 영역에서 살아남은 객체가 여기로 복사됨

대부분 Young 영역보다 크게 할당 하며,크기가 큰 만큼 young 영역보다 Gc는 적게 발생함

old 영역에 데이터가 가득차면 GC 를 수행하는데 GC 알고리즘 수행됨.

 

 

 

 

 

 

 

'JAVA > JAVA' 카테고리의 다른 글

[자료구조]List  (0) 2019.04.28
jvm 메모리 구조  (0) 2019.04.22
[객체지향] JAVA SOLID 원칙  (0) 2019.02.23
제네릭 메소드  (0) 2017.05.17
제네릭 개념 알기  (0) 2017.05.16
Posted by 양승아
:

jvm 메모리 구조

JAVA/JAVA 2019. 4. 22. 21:24 |

jvm 이란?

Jave Virture Machine 의 약자로 자바 가상머신이라 부른다.

자바와 운영체제사이에서 중계자 역할을 한다.

자바가 운영체제 종류에 영향받지 않고 돌아갈 수 있도록 한다.

메모리 관리를 자동으로 해준다(GC)

 

 

JVM은 운영체제와 플랫폼 종류에 의존적이지 않고 독립적으로 JAVA 프로그램이 실행된다.

 

<자바실행과정>

java Compiler 에 의해 .java 파일은 Byte code로 변환된다

Class Loader는 변환된 Byte Code 파일을 Jvm 내로 class를 로드하고 Link 작업을 통해 배치등 일련의 작업을 한다.

런타임시 .class를 load 한다.

Execution Engine(실행엔진) Class Loader를 통해 JVM 내부로 넘어와 Runtime Data Area에 배치된 Byte Code 들을 명령어 단위로 실행시킴

* GC 는 어플리케이션이 생성한 객체 생존 여부를 판단하여, 더이상 참조되지 않거나 null 인 객체의 메모리를 해체시켜 메모리를 반납을 함

* Runtime Data Area(JVM) 런타임 데이터 영역은 JVM 메모리로 java 어플리케이션이 실행하면서 할당받은 메모리 영역이다

 

 

Method Static Area : 클래스,변수,Method,Static변수,상수 정보들이 저장되는 영역

Heep Area : new 명령어로 생성된 인스턴스와 객체가 저장되는 구역. GC 이슈는 이영역에서 일어남

Stack Area : Method 내에서 상용되는 값들(매개변수, 지역변수, 리턴값) 메소드가 호출될때 LIFO 로 생성됨.실행이 완료되면 LIFO 삭제

PC Register : CPU의 Register와 비슷한 역할함. 현재 수행중인 JVM명령의 주조값이 저장됨

 

* Method Satic Area , heep..영역은 모든 스레드에서 공유할 수 있다.

 

Young Generation : 객체가 생성될때 마다 저장된다. 즉 막 생성된 객체들의 인큐베이터이다. 생성된 기간이 흐르고 우선순위가 낮아지면

Young 세대의 객체들은 Old 세대로 이동하게 된다. 이영역은 객체가 사라질 때는 Minor GC 수행된다.

Old Generation : young Generation 영역에 있는 객체가 오래되서 저장되는 공간이다.이영역에서 사라질때는  Full GC 수행됨

Permanent Generation : 클래스 로더에 의해 로드되는 클래스,메소드 등에서 대한 메타정보가 저장되는 영역으로 JVM 에 의해 사용됨

 

'JAVA > JAVA' 카테고리의 다른 글

[자료구조]List  (0) 2019.04.28
Garbage Collector  (0) 2019.04.23
[객체지향] JAVA SOLID 원칙  (0) 2019.02.23
제네릭 메소드  (0) 2017.05.17
제네릭 개념 알기  (0) 2017.05.16
Posted by 양승아
:

#SOLID 원칙

java 가 객체지향언어로서 객체지향의 solid 5대 원칙을 알아보자.



#Single Responsibility principle (SRP)


작성된 클래스는 하나의 기능만 가져야 한다. 

하나의 책임에 집중 -> 책임 영역 확실해짐

다른 책임의 변경으로 연쇄작용에서 자유로워짐

유지보수가 용이해짐 

도메인이해가 필요함


적용방법

- 두클래스가 중복되고비슷한 책임을 갖고 잇다면 부모클래스로 정의하여 부모클래스에 위임하고 

각각 클래스에서는 유사한 책임은 부모클래스에 명백히 위임하고 각각 다른 기능을 정의한다.


적용사례 

/**
*
* single responsibility principle 적용되기 전 클래스
*
*
*/
public class Guitar {

//생성자
public Guitar(String serialNumber,Double price, Maker maker, String model, int stringNum) {

}

private String seriaNumber;
private Double price;
private Maker maker;
private String model;
private int stringNum;

}


우선 변화 요소 유무 부터 나누면 

serialNumber 은 고유정보이다. 다른 클래스와 구분되는 정보이다.

price,Meker,model,stringNum 등은 특성 정보로 변경이 발생 할 수 있는 부분이다. 

따라서 특정 정보군에 변화가 발생하면 항상해당 클래스를 수정해야 하는 부담이 발생하게 됨으로 이부분을 SRP 이 적용대상이 된다.


변경이 예상되는 객체들을 따로 분리한다. 

model,price,Maker,StringNum 을 Spec 클래스에 모아둔다


class Gutar{

public Gutar(String serialNumber,GuitarSpec spec ) {
}
}


class GuitarSpec{
double price;
String model;
Maker maker;
int StringNumber;
}

만약 GuitarSpec 에 name 이라는 필드가 추가되도 guitar 클래스에서 책임지지 않아도 된다. 스펙 클래스에서만 추가해주면 된다.

이렇게 각 객체간 응집력을 높이고 결합력이 있다고 분리시켜 객체간의 순 작용 할 수 있도록 한다.


#Open Close Principle(OCP)


확장에는 열려있고 변경에는 닫혀있어야 한다.

즉 추가 요구 사항이나 변경 사항이 있더라도 기존 구성요소에 수정이 일어나지 않고 확장하여 재사용할 수 있어야함.

OCP는 관리가능하고 재사용 가능한 코드를 만드는 기반임

추상화와 다형성을 통해 OCP 를 가능케함


적용방법

- 변경(확장)될 것과 변하지 않을 것을 구분

- 이 두 모듈이 만나는 지점에 인터페이스 정의(?) -> 공통되는 부분을 부모클래스로 만들기

- 구현에 의존하기보다 정의한 인터페이스에 의존하도록 코드 작성


예를 들어보자 SRP 예에 들었던 Guitar 뿐만 아니라 바이올린 ,첼로 등등등 악기들을 추가 해야된다고 생각해보자.

Guitar, GuitarSpect 는 오로지 기타를 위한 클래스로 만들어졌다. 결합도 높게 설계햇다면 확장적이지 못할 뿐더러 많은 수정이 발생되어 유지보수가 어렵다.

기타와 바이올린에 getPlay()라는 메소드를 추가한다고 가정하면 해당 클래스 모두 수정이 필요하다.


OCP 원칙대로 수정해보자

우선 기타와 추가될 악기들의 공통 속성들을 모두 담을수 있는 악기 인터페이스와 추가될 알기 스텍들과 공통이 될수 있는 속성을 스펙 인터페이스로 만든다.

악기, 악기 스펙은 수정이 없으면서 악기는 계속 확장적이게 된다. 상위클래스나 인터페이스는 일종의 완충 장치인것이다.




악기스펙 인터페이스에서는 가격정보,모델정보,연주하기() 메서드를 정의하고 각각 기타,바이올린 등 추가되는 악기 클래스에서 입맛에 맞게 메서드를 재저의하면 되다.

더 깔금한 예시로 postgreSQL, Oracle, sybase 데이터베이스에 모두 확장적이면서 자바어플리케이션 입장에서 수정은 폐쇄적인것 임을 알아야한다. 

이것이 바로 OCP 이다.


 

ocp jdbc interface에 대한 이미지 검색결과





#Liskov Substitution Principle(LSP)


하위 클래스의 인스턴스는 상위형 객체 참조 변수에 대입해 상위 클래스의 인스턴스 역할을 하는데 문제가 없어야 한다.

즉 하위클래스가 상위클래스 역할을 대신할 때 논리적으로 맞아야 한다.


' A is a kind of B  즉 a kind of B is A '


잘못된 상속 관계 : 엄마와 딸 // 딸은 아버지의 한 종류다 ?  NO !!

올바른 상속 관계 : 고양이와 동물 // 고양이는 동물의 한 종류다 ? YES !!


객체지향에서의 상속은 상위,하위 클래스를 설계하는 것이 계층이 아니라 분류이다. 상속은 확장이다 라고 생각해야한다.


아래 간단한 예제로 이해해보자.

void fuction(){
LinkedList list = new LinkedList();
modify(list);
}

void modify(LinkedList list){
list.add("test");
doSomethingWith(list);

}

List만 사용할 것이라면 이 코드도 문제는 없다. 만약 속도 개선을 위해 HashSet을 사용해야 하는 경우가 발생한다면 LinkdList 를 다시 HashSet으로 어떻게 변경할수 있을까 ? LinkdList 와 HashSet 은 Collection 인터페이스를 상속하고 있으므로 아래와 같이 구현할수 있다.


void fuction(){
Collection collection = new HashSet();
modify(collection);
}

void modify(Collection collection){
collection.add("test");
doSomethingWith(collection);

}

Collection 프레임 워크가 LSP를 준수하지 않았다면 Collection 인터페이스를 통해 수행하는 작업이 제대로 동작하지 않았을것이다.

LSP 준수하여 HachSet는 modify() 메소드 동작이 가능하다. 또한 OCP 구조도 된다. modify()는 컬렉션에는 확장이 열러있고 modify 에 변경은 닫혀있다.



#InterFace Segregation Principle(ISP)


인터페이스 분리 원칙은 SRP와 같은 맥락의 대한 다른 해결책을 제시하는 것이다. 

한 클래스에 너무 많은 책임을 주어 상황에 관련 되지 않은 메소드 까지 구현되어 있다면, 

SRP 원칙은 기존 클래스를 여러 책임 단위로 쪼갠다.

하지만 ISP는 기존 클래스를 그대로 두고 인터페이스 최소주의 원칙에 따라 각 상황에 맞는(책임) 기능만 제공하도록 인터페이스로 분리한다고 생각하면 된다.


job클래스에 요리하기 (), 기도하기(), 사격하기(), 개발하기() 메소드가 있다. 하지만 모든 사람 하는 기능은 아니다.



public class Job {

void shoot(){};
void pray(){};
void cook(){};
void develop(){};

}


각각 직업 특성에 맞게 책임을 인터페이스로 분리해보자

우선 책임별 인터페이스 생성한다.


interface Shootable {
void shoot();
}

interface Cookable {
void cook();
}


interface Prayable {
void pray();
}


interface Developable {
void develop();
}


그다음 다중구현을 통해 각각 메서드를 오버라이딩해서 재정의한다.


public class job implements Shootable,Developable,Cookable,Prayable{
@Override
public void shoot() {
System.out.println("사격한다.");
}

@Override
public void cook() {
System.out.println("요리한다");
}

@Override
public void pray() {
System.out.println("기도한다.");
}

@Override
public void develop() {
System.out.println("개발한다.");
}
}

public class ISPmain {

public static void main(String[] args){

Developable developer = new job();
developer.develop();

Cookable cooker = new Person();
cooker.cook();
}
}

직업중에 개발자라면 위에 예제와 같이 참조형을 Developable 타입으로 정의하고 job 인스턴스를 받으면 개발자는 develop() 기능만 할당 받게 된다.

상황에 맞게 기존 클라이언트는 변경없이 관련 메소드만 제한을 강제하여 사용할 수 있다.


#Dependency Inversion Principle (DIP)


'추상화 된 것은 구체적인 것에 의존하면 안된다. 구체적인 것이 추상화 된 것에 의존해야 한다.'


즉 자신보다 변하기 쉬운 것에 의존하지 마라.

구체적으로 추상클래스 또는 상위클래스는 구체적인 구현클래스 또는 하위클래스에게 의존적으면 안된다. 

왜냐면 구체적인 클래스는 코딩에 있어서 가장 전면적으로 노출되고 사용되기 때문에 시시때때로 변화할 수 있으므로 변화에 민감하다.


예를 들면 BMW 자동차는 스노우타이어를 장착하고 있다. 하지만 스노우 타이어는 계절의 영향을 받아 겨울 지나고 다른 타이어로 교체할것이다.



BMW가 자신보다 더 변화에 민감한 스노우 타이어를 의존하고 있다. 이 의존을 일방적인 방향을 역전 시켜보자



자신 보다 변하기 쉬운 것에 의존하던것을 추상화 된 인터페이스나 상위클래스를 두어 변하기 쉬운것의 변화에 영향 받지 않게 의존 방향을 역전시켰다.

타이터 인터페이스에 의존하면서 직접적으로 스노우,일반타이어와 의존하는것을 피했다.

또 스노우,일반 타이어는 기존에 어떤 것도 의존하지 않았지만 인터페이스를 의존해야한다. 이것이 Dependency Inversion Principle 이다.


#마무리


객체지향 OOP 의 4대 요소인 캡슐화,상속,추상화,다형성이라는 재료와 객체지향 성계 SOLID 원칙을 통해 객체지향을 어떻게 설계하는지 배웠다.

결국 실무에서 설계를 잘해야 유지보수 측면에서 굉장히 용이하고 개발 시간과 비용을 절감할수 있다. 

 


'JAVA > JAVA' 카테고리의 다른 글

Garbage Collector  (0) 2019.04.23
jvm 메모리 구조  (0) 2019.04.22
제네릭 메소드  (0) 2017.05.17
제네릭 개념 알기  (0) 2017.05.16
다형성  (0) 2015.08.28
Posted by 양승아
:

제네릭 메소드

JAVA/JAVA 2017. 5. 17. 17:08 |

제네릭 메소드(Generic method)


제네릭 메소드에 대해 전에 간단하게 포스팅 했었는데 오라클 레퍼런스 설명 기반으로 포스팅하려고 한다.

제네릭 메서드는 타입매개변수를 가진 메소드이다. 제네릭타입을 선언하는 것과 비슷하지만 타입매개변수의 스코프는 매서드로 제한된다.(?)


제네릭 메서드 문법은 return 타입 전에 <>사이 타입에 타입매개변수를 표기한다.

static generic 메서드를 위해 타입매개변수는 반드시 메서드의 return타입 이전에 위치해야한다.


아래의 코드를 보면

Util 클래스는 두 Pair 객체를 비교하는 generic 메소드를 포함하고 있다. 




public class Util {
    public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
        return p1.getKey().equals(p2.getKey()) &&
               p1.getValue().equals(p2.getValue());
    }
}

public class Pair<K, V> {

    private K key;
    private V value;

    public Pair(K key, V value) {
        this.key = key;
        this.value = value;
    }

    public void setKey(K key) { this.key = key; }
    public void setValue(V value) { this.value = value; }
    public K getKey()   { return key; }
    public V getValue() { return value; }
}

두 메소드를 호출한 문장은 아래와 같다.

Pair<Integer, String> p1 = new Pair<>(1, "apple"); Pair<Integer, String> p2 = new Pair<>(2, "pear"); boolean same = Util.<Integer, String>compare(p1, p2);


Util.<Integer, String>compare(p1, p2);

<>안에 타입을 명시하여 타입인자는 컴파일러가 타입 추론한다. <>안에 타입 명시하지 않고 generic 메서드가

아닌 일반 메서드를 호출해도 타입추혼이 이루어 진다. 




'JAVA > JAVA' 카테고리의 다른 글

jvm 메모리 구조  (0) 2019.04.22
[객체지향] JAVA SOLID 원칙  (0) 2019.02.23
제네릭 개념 알기  (0) 2017.05.16
다형성  (0) 2015.08.28
클라이언트 ip 구하기  (0) 2015.08.13
Posted by 양승아
:

제네릭 개념 알기

JAVA/JAVA 2017. 5. 16. 15:29 |

java 재네릭


재네릭은 클래스 내부에서 사용할 데이터타입을 외부에서 지정하는 기법을 의미한다.

데이터타입을 외부에서 지정하면 장점뭘까?

메소드 선언에 사용되는 파라미터 형식처럼, 타입 파라미터는 다른 입력값을 같은 코드를 재사용 할 수 있는 방법을 제시한다.

다른점은 형식 파라미터는 값이 아니라 입력이다.

타입파라미터는 타입이 입력!


제네릭 없이 캐스팅이 필요한 코드

List list = new ArrayList(); list.add("hello"); String s = (String) list.get(0);


제네릭을 사용하여 코드 작성시,캐스팅이 필요 없어진다.

List<String> list = new ArrayList<String>(); list.add("hello"); String s = list.get(0); // no cast


제네릭을 사용함으로써 일반적인 알고리즘을 구현하도록 지원한다.

generics를 사용하면서 다양한 타입들의 콜렉션을 사용할 수 있고 더 안정적이고 읽기 쉬운 코드를 일반적인 알고리즘으로 구현할 수 있다.


좀더 자세히 알아보자.

아래의 코드를 살펴보자.

class Person<T>{
 public T info; 
}
 public class GenericDemo{
  
  public static void main(String[] arge){
    Person<String> p1 = new Person<String>();
    Person<StringBuilder> p2 = new Person<StringBuilder>();
  } 
}



데이터 타입 결과는 

p1.info = String

p2.info = StringBuilder


각각의 인스턴스를 생성할 때 사용한 <> 사이에 어떤 데이터 타입을 사용했느냐에 달려있다.


클래스 선언부

public T info;


클래스 필드 info의 데이터 타입은 T로 되어있다. 실제로 T라는 데티어 타입은 존재하지 않는다.

이값은 아래 코드의 T에서 정해진다.


제너릭 클래스 선언부

class Person<T>{


제네릭 클래스의 인스턴스 생성부

Person<String> p1 = new Person<String>();

제네릭 클래스의 인스턴스 생성시 <String> 으로 지정하면서 제네릭 T info는 String info 가 된다.


재네릭 사용하는 이유


class StudentInfo{
    public int grade;
    StudentInfo(int grade){ this.grade = grade; }
}

class StudentPerson{
    public StudentInfo info;
    StudentPerson(StudentInfo info){ this.info = info; }
}

class EmployeeInfo{
    public int rank;
    EmployeeInfo(int rank){ this.rank = rank; }
}
class EmployeePerson{
    public EmployeeInfo info;
    EmployeePerson(EmployeeInfo info){ this.info = info; }
}
public class GenericDemo {
    public static void main(String[] args) {
        StudentInfo si = new StudentInfo(2);
        StudentPerson sp = new StudentPerson(si);
        System.out.println(sp.info.grade); // 2
        EmployeeInfo ei = new EmployeeInfo(1);
        EmployeePerson ep = new EmployeePerson(ei);
        System.out.println(ep.info.rank); // 1
    }
}


위 코드를 보면 StudentPerson와 EmployeePerson가 중복되는 클래스이다.

f(x) = x 함수 클래스로 x 매개변수를 제네릭 클래스로 구현하여 StudentPerson와 EmployeePerson 클래스중복을 제거해보자.


class StudentInfo{
    public int grade;
    StudentInfo(int grade){ this.grade = grade; }
}
class EmployeeInfo{
    public int rank;
    EmployeeInfo(int rank){ this.rank = rank; }
}
class Person<T>{
    public T info;
    Person(T info){ this.info = info; }
}
public class GenericDemo {
    public static void main(String[] args) {
        Person<EmployeeInfo> p1 = new Person<EmployeeInfo>(new EmployeeInfo(1));
        EmployeeInfo ei1 = p1.info;
        System.out.println(ei1.rank); // 성공
         
        Person<String> p2 = new Person<String>("부장");
        String ei2 = p2.info;
        System.out.println(ei2.rank); // 컴파일 실패
    }
}

 

기본 데이터 타입과 제네릭

제네릭은 참조 데이터 타입에 대해서만 사용할 수 있다. 기본 데이터 타입에서는 사용할 수 없다. 따라서 아래 코드의 int는 오류난다.

int . char, double ..등등 은 기본데이터로 사용할 수 없다. int 대신 integer 로 대신하여 사용할 수 있다.

class EmployeeInfo{
    public int rank;
    EmployeeInfo(int rank){ this.rank = rank; }
}
class Person<T, S>{
    public T info;
    public S id;
    Person(T info, S id){ 
        this.info = info; 
        this.id = id;
    }
}
public class GenericDemo {
    public static void main(String[] args) {
        Person<EmployeeInfo, int> p1 = new Person<EmployeeInfo, int>(new EmployeeInfo(1), 1);
    }
}
 

복수 제네릭

클래스 내에서 여러개의 제네릭을 필요로 하는 경우 아래의 코드를 참조하자.

class EmployeeInfo{
    public int rank;
    EmployeeInfo(int rank){ this.rank = rank; }
}
class Person<T, S>{
    public T info;
    public S id;
    Person(T info, S id){ 
        this.info = info;
        this.id = id;
    }
}
public class GenericDemo {
    public static void main(String[] args) {
        EmployeeInfo e = new EmployeeInfo(1);
        Integer i = new Integer(10);
        Person<EmployeeInfo, Integer> p1 = new Person<EmployeeInfo, Integer>(e, i);
        System.out.println(p1.id.intValue());
    }
}
 

재네릭 메소드 사용

class EmployeeInfo{
    public int rank;
    EmployeeInfo(int rank){ this.rank = rank; }
}
class Person<T, S>{
    public T info;
    public S id;
    Person(T info, S id){ 
        this.info = info;
        this.id = id;
    }
    public <U> void printInfo(U info){
        System.out.println(info);
    }
}
public class GenericDemo {
    public static void main(String[] args) {
        EmployeeInfo e = new EmployeeInfo(1);
        Integer i = new Integer(10);
        Person<EmployeeInfo, Integer> p1 = new Person<EmployeeInfo, Integer>(e, i);
        p1.<EmployeeInfo>printInfo(e);
        p1.printInfo(e);
    }
}
 
재네릭 인스턴스 생략 가능하다. 아래와 같이 p1,p2 모두 정상적으로 생성된다.
Person<EmployeeInfo, Integer> p1 = new Person<EmployeeInfo, Integer>(e, i);
Person p2 = new Person(e, i);


extends 로 재네릭으로 올 수 있는 데이터 타입을 특정 클래스의 자식으로 제한할 수 있다.

extends는 상속 관계인 클래스 뿐만 아니라 구현(implements)의 관계에서도 사용할 수 있다.

interface Info{
    int getLevel();
}
class EmployeeInfo implements Info{
    public int rank;
    EmployeeInfo(int rank){ this.rank = rank; }
    public int getLevel(){
        return this.rank;
    }
}
class Person<T extends Info>{
    public T info;
    Person(T info){ this.info = info; }
}
public class GenericDemo {
    public static void main(String[] args) {
        Person p1 = new Person(new EmployeeInfo(1));
        Person<String> p2 = new Person<String>("부장");
    }
}



제네릭에 대해 기본적인 개념만 살펴보았다.


'JAVA > JAVA' 카테고리의 다른 글

[객체지향] JAVA SOLID 원칙  (0) 2019.02.23
제네릭 메소드  (0) 2017.05.17
다형성  (0) 2015.08.28
클라이언트 ip 구하기  (0) 2015.08.13
java foreach 반복문  (0) 2015.08.13
Posted by 양승아
:

다형성

JAVA/JAVA 2015. 8. 28. 18:43 |

다형성


이전에 포스팅했엇는데 패턴 공부 하면서 다시한번 개념 잡기 위해 공부!!



//추상클래스 A
abstrct class A{
 int left,right;
 public void setInt(int left, int right){
  this.left = left ; 
  this.right = right ;
 }
 int sum(){
  return this.left + this.right;
 }
 public abstract void sum();
 public void run(){
    sum();
 }
}

class B extend A {
 public void sum(){
   System.out.println("+++sum :" +sum()); 
 }
}

class C extends A {
 public void sum(){
  System.out.println("---sum : " + sum )
 }
}
public class D {
  public static void execute(A a){
    System.out.println("실행결과");
    a.run();
  }
  public static void main(String[] arg){
   A a1= new B();
   A a2 = new C();
  
  a1.setInt(10,20);
  a2.setInt(10,20);

  execute(a1);
  execute(a2);
 
 }
}





'JAVA > JAVA' 카테고리의 다른 글

제네릭 메소드  (0) 2017.05.17
제네릭 개념 알기  (0) 2017.05.16
클라이언트 ip 구하기  (0) 2015.08.13
java foreach 반복문  (0) 2015.08.13
JAVA 앞뒤 공백제거 trim()  (0) 2015.08.13
Posted by 양승아
:

JAVA 클라이언트 IP 구하기


클라이언트 ip 가져오는 방법은 아래와 같다.


Request.getRemoteAddr();

Requset 객체의 getRemoteAddr() 메소드를 호출한다.

로컬로 테스트 한다면 127.0.0.1 의 값을 가져올것이다.


만약 IPv6 형식(0:0:0:0:0:0:01)과 같은 형식으로 반환되면 

eclipse 환경 변수 설정 다이얼로그 띄운다.


Run -> Run Confiugations -> 좌측트리메뉴에서 Apache Tomcat 서버 선택 

-> Arguments 탭 메뉴 선택 -> VM Arguments 텍스트 박스 영역


"-Djava.net.preferIPv4Stack=true"

텍스트 박스 가장 하단에 위의 코드를 추가함





또는  톰캣서버 환경 설정 파일에서 직접 변경하기

\bin\catalina.bat 파일열기 

set JAVA_OPTS 검색하여


:noJuliConfig

set JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG%


:noJuliManager
set JAVA_OPTS=%JAVA_OPTS% %LOGGING_MANAGER%


위의 2개의 설정 값에  -Djava.net.preferIPv4Stack=true 추가 해준다



:noJuliConfig

set JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG% -Djava.net.preferIPv4Stack=true


:noJuliManager
set JAVA_OPTS=%JAVA_OPTS% %LOGGING_MANAGER% -Djava.net.preferIPv4Stack=true



위처럼 추가하면 127.0.0.1 로 나온다~!


'JAVA > JAVA' 카테고리의 다른 글

제네릭 개념 알기  (0) 2017.05.16
다형성  (0) 2015.08.28
java foreach 반복문  (0) 2015.08.13
JAVA 앞뒤 공백제거 trim()  (0) 2015.08.13
[java] URL(xml파일) java 파싱하는 방법  (0) 2015.08.12
Posted by 양승아
: