달력

5

« 2024/5 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

'jdk5.0'에 해당되는 글 2

  1. 2007.08.14 JDK 5.0의 새로운 기능 Annotation
  2. 2007.08.13 JDK 5.0의 새로운 기능 Generics 1
2007. 8. 14. 10:57

JDK 5.0의 새로운 기능 Annotation 그거/Java2007. 8. 14. 10:57

o annotation
  : source code에 사용하는 meta-tag

  @MyAnnotation(doSomething="What to do")
  public void myMethod() {
      ....
  }

  - JDK5.0에서 사용가능한 2가지 Annotation

    Simple Annotations : custom annotation type은 생성할 수 없는 기본으로 제공되는 Annotation.
    Meta Annotations : annotation-type 선언에 대한 annotation. 즉, annotation의 annotation

  - Simple Annotations

    기본으로 제공되는 annotation에는 3가지가 있다.

    1) Override
    super class의 method를 꼭 override 해야 됨을 표시.
    이 annotation을 사용한 method가 super class의 method를 override 하지 않으면, compile시 오류 발생

    Example:

    @Override
    public Strig tostring() {
       return super.toString() + " Testing annotation name : 'Override'";
    }

    위 예제처럼 Object class의 toString() method를 override하기 위해 annotation @Override를 사용한 후에 compile을 하면
    아래와 같은 오류가 발생한다.

       Compiling 1 source file to D:tempNew Folder (2)
                                     TestJavaApplication1buildclasses
       D:tempNew Folder (2)TestJavaApplication1srctest
          myannotationTest_Override.java:24: method does not override
                       a method from its superclass
       @Override
       1 error

 2) Deprecated
    code에 deprecated된 method등을 사용시에 compiler가 deprecated 된 부분에 대해서 warning을 보여주도록 함.

    Example:

    public class TestDeprecated {
       
@Deprecated
        public void doSomething() {
            System.out.println("Testing annotation name : 'Deprecated'");
        }
    }

    public class TestAnnotations {
        public static void main(String[] args) {
            new TestAnnotations();
        }

        public TestAnnotations() {
            TestDeprecated t2 = new TestDeprecated();
                  t2.doSomething();
        }
    }

    위 소스를 컴파일 해보면 둘 다 문제없이 compile이 되지만, TestAnnotations class는 compile시
    t2.doSomething() 부분에서 deprecated 된 method가 사용되고 있다고 warning을 보여준다.

 3) SuppressWarnings
    compiler에게 warning에 대해서 무시하도록 지시.

    Example:

    public class TestAnnotations {
        public static void main(String[] args) {
            new TestAnnotations().doSomeTestNow();
        }

      
@SuppressWarnings("deprecation")
       public void doSomeTestNow() {
           TestDeprecated t2 = new TestDeprecated();
           t2.doSomething();
       }
    }

   Deprecated annotation에서 사용했던 예제를 위와 같이 수정한 후에 compile 하면,
   전에 보였던 warning message가 보이지 않는 것을 확인할 수 있다.

o annotation type
  : annotation을 정의하는 type. custom annotation을 정의할 때 사용

  public @interface MyAnnotation {
      String toSomething();
  }

  - 3 annotation types

 1) Marker annotation
    annotation에 element 없이 이름 자체만으로 사용하는 경우

    Example:

       public @interface MyAnnotation {
    }

    Usage:

    @MyAnnotation
    public void myMethod() {
    }

 2) Single-Element
    annotation에 element를 하나 사용하는 경우
    data=value 또는 value 만 () 안에 사용

    Example:

    public @interface MyAnnotation {
      String doSomething();
      }

      Usage:

    @MyAnnotation("What to do")
    public void myMethod() {
        ....
    }

 3) Full-value or Multi-value
    annotation에 data를 여러개 사용하는 경우
    data=value 형식으로 ()안에 사용

    Example:

    public @interface MyAnnotation {
     int count;
     String date;
        String doSomething();
    }

    Usage:

    @MyAnnotation(doSomething="What to do", count=1, date="09-09-2005")
    public void myMethod() {
        ....
    }


  - Annotation type 정의 규칙
    Annotation 선언시 '@'다음에 interface keyword, '@' 다음에 annotation 이름의 형식으로 '@'로 시작해야 한다.
    method 선언에 대해서는 parameter, throws 절이 있어선 안된다.
    method의 반환 타입은 다음 중 하나여야 한다.
      primitives
      String
      Class
      enum
      array of the above types


- 4 meta-annotation

 1) Target

class의 어떤 element에 annotation이 적용 가능한지를 나타내는 annotation

   - Target annotation의 value
     @Target(Element.TYPE)                : class의 어떤 element 에나 적용 가능함
     @Target(Element.FIELD)               : field 또는 property에만 적용 가능함
     @Target(Element.METHOD)              : method level에서 적용 가능함
     @Target(Element.PARAMETER)           : method의 parameter에 적용 가능함
     @Target(Element.CONSTRUCTOR)         : 생성자에 적용 가능함
     @Target(Element.LOCAL_VARIABLE)      : local variables에 적용 가능함
     @Target(Element.ANNOTATION_TYPE)     : 선언된 유형 자체가 annotation 임을 가르킴

  
   Example:

   // annotation 정의
   @Target(ElementType.METHOD)
   public @interface Test_Target {
          public String doTestTarget();
   }

   // 위에서 정의한 annotation을 사용하는 class
   public class TetAnnotations {
       public static void main(String[] args) {
           new TestAnnotations().doTestTarget();
       }

      @Test_Target(doTestTarget="Hello World!")
       public void doTestTarget() {
           System.out.println("Testing Target Annotation");
       }
   }

   위 예제를 보면 Test_Target 이라는 custom annotation이 method level(ElementType.METHOD)로 정의되어 있기 때문에
      @Test_Target(doTestTarget="Hello World!") 를 아래와 같이 method가 아닌 field level로 이동하면 오류가 발생한다.

   public class TetAnnotations {
       @Test_Target(doTestTarget="Hello World!")
       private String str;

       public static void main(String[] args) {
           new TestAnnotations().doTestTarget();
       }

       public void doTestTarget() {
           System.out.println("Testing Target Annotation");
       }
   }


 2) Retention

annotation이 얼마 동안 유지되는지 여부를 나타내는 annotation

   - Retention annotation의 value
     RetentionPolicy.SOURCE    : source level에서 유지되며, compiler에서는 무시됨
     RetentionPolicy.CLASS     : compiler에 의해서 compile time에 유지됨
     RetentionPolicy.RUNTIME   : VM에 의해 유지되고, runtime에만 읽을 수 있음.

   Example:

   @Retention(RetentionPolicy.RUNTIME)
   public @interface TestRetention {
       String doSomeTestRetention();
   }


 3) Documented

   javadoc tool에 의해서 문서로 만들어져야 되는 부분을 나타냄


   Example:

   @Documented
   public @interface TestDocumented {
       String getDocumented();
   }

   public class TestAnnotations {
       public static void main(String[] args) {
        new TestAnnotations().doSomeTestRetention();
        new TestAnnotations().doSomeTestDocumented();
    }

    @TestRetention(doTestRetention='Hello retention test")
    public void doSomeTestRetention() {
        System.out.println("Test annotation 'Retention'");
    }

    @TestDocumented(doTestDocumented='Hello Documented")
    public void doSomeTestDocumented() {
        System.out.println("Test annotation 'Documented'");
    }
   }

 4) Inherited

 

  이 annotation이 붙으면 해당 class는 자동으로 상속된 class 임을 나타낸다.

   Example:

  @Inherited
   public @interface TestInherited {
       boolean isInherited() default true;
    String doSomething() default "Do What?";
   }

   @TestInherited
   public class TestAnnotations {
       // no implementation for TestInherited class
   }

   위 예를 보면 TestAnnotations class는 TestInherited의 method를 implements할 필요가 없다.
   @TestInherited annotation을 통해 자동으로 상속이 이루어지기 때문이다.

   old-style-java way

   public class TestAnnotations implements TestInherited {
       public boolean isInherited() {
        return false;
    }

    public String doSomething() {
        return "";
    }

    public boolean equals(Object obj) {
        return false;
    }

    public int hashCode() {
        return 0;
    }

    public String toString() {
        return "";
    }

    public Class annotationClass() {
        return null;
    }
   }

   위 예제를 보면 TestInherited의 method 뿐만 아니라, Object class의 method인 equals(), hashCode(), toString() method와
   java.lang.annotation.Annotation class의 method인 annotationClass() method까지 원하던 원하지 않던 override를 해야 한다.


 

'그거 > Java' 카테고리의 다른 글

[Java Quiz] 주민등록 번호와 바코드 유효성 체크  (0) 2007.09.12
Java Anti-Pattern  (2) 2007.08.20
JDK 5.0의 새로운 기능 Generics  (1) 2007.08.13
java Collection 들  (0) 2007.08.10
객체의 hashcode에 대한 고찰  (0) 2007.08.09
:
Posted by 뽀기
2007. 8. 13. 11:01

JDK 5.0의 새로운 기능 Generics 그거/Java2007. 8. 13. 11:01

# Generics

@ 특징
  1. Collection 사용시 Type-Safe 한 Collection을 사용할 수 있다.(Compile time type safety)
  2. 이전에는 Collection에 어떤 객체든 넣을 수 있었지만, 지정 객체만 넣음으로써
     실행시간이 아닌 컴파일 시점에 오류를 미리 체크할 수 있다.
  3. Collection 사용시 Casting 작업이 필요 없다.
 

  기존 코드

  List myList = new ArrayList();
  myList.add(new String("this is a test");
  myList.add(new Integer(100));

 // 실행 시간에 오류가 체크됨
  Integer integer = (Integer)myList.iterator().next();


  변경 코드

  List<Integer> myList = new ArrayList<Integer>();
 
 // 컴파일 시점에 오류가 체크됨
  myList.add(new String("this is a test");
  myList.add(new Integer(100));

  Integer integer = (Integer)myList.iterator().next();

@ 선언 방법 및 사용 방법

  < > 기호를 사용한다.
  E : 선언하여 사용할 때 들어가는 실제 데이터 타입

public class ArrayList<E> extends AbstractList<E> {
      public boolean add(E o) {
          ....
      }
  }

  String 객체만 담을 수 있는 ArrayList를 만들 경우 아래와 같이 한다.

  List<String> arrayList = new ArrayList<String>();

  이 경우 위 선언에서 봤던 E 는 String 이 되며, 위 선언은 아래와 같이 변경된다고 보면 된다.

  public class ArrayList<String> extends AbstractList<String> {
        public boolean add(String o) {
             ....
        }
  }

  또한, 아래와 같이 특정 부류(?)에 대해서만 적용이 가능한 선언을 할 수도 있다.

                                 Animal
                                  / \
                                 /   \
                                /     \
                              Dog      Cat

※ Dog, Cat class는 Animal class를 상속받음

  위와 같이 클래스가 구성되어 있고, 동물병원에서 현재 병원에 있는 모든 동물들의 목록을 뽑고자 한다면
  아래와 같이 하면 된다.

  // 현재 병원에 있는 동물들의 목록
  List<Animal> animals = new ArrayList<Animal>();
  animals.add(new Dog());
  animals.add(new Cat());
  animals.add(new Dog());
  animals.add(new Dog());
  animals.add(new Cat());
  animals.add(new Dog());

  public void printAnimals(ArrayList<Animal> list) {
      for( Animal a : list ) {
          System.out.println(a);
      }
  }

  이와 같이 printAnimals() 라는 method에 병원의 동물들의 목록이 들어가있는 animals(ArrayList<Animal>) 객체를 넘겨서
  각 동물들의 정보를 찍을 수 있다.

  그런데, 병원에 있는 동물들의 목록을 동물별로 따로 뽑고 싶을 경우는 어떻게 해야 될까?
  아래와 같이 강아지들만의 목록이 따로 있다고 하면,

  List<Dog> dogs = new ArrayList<Dog>();
  dogs.add(new Dog());
  dogs.add(new Dog());
  dogs.add(new Dog());
  dogs.add(new Dog());
  dogs.add(new Dog());

  위에서 정의된 printAnimals(ArrayList<Animal> list) method로는 강아지들 정보만 있는 dogs(ArrayList<Dog>) 객체를 넘겨서
  각 강아지에 대한 정보를 찍을 수 없다.

  왜냐하면, printAnimals(ArrayList<Animal> list) method는 인자로 ArrayList<Animal>만 받을 수 있도록 되어 있기 때문이다.
  그렇다고 해서 printAnimals(ArrayList<Dog> list) method를 추가한다고 해서 해결되지도 않는다.
  중복된 method라고 컴파일시 오류가 발생하기 때문이다.

  그러면 어떻게 해야 될까? 바로 아래와 같이 와일드카드를 이용해서 generics를 확장시켜야 한다.

  public <T extends Animal> void printAnimals(ArrayList<T> list) {
      for( Animal a : list ) {
          System.out.println(a);
      }
  }

  public void printAnimals(ArrayList<? extends Animal> list) {
      for( Animal a : list ) {
          System.out.println(a);
      }
  }

  T : 앞에서 말했던 E 와 같은 개념이다.
  extends : 확장, 상속, 구현 등의 개념으로써, 간단하게 'T extends Animal' 은 T는 Animal 부류이다(T의 하위 클래스) 라고 생각하면 된다.

  위의 두 가지 선언은 같은 기능을 하며,  아래와 같이 여러가지로 작동한다고 보면 된다.

  public void printAnimals(ArrayList<Dog> list) {
      for( Dog a : list ) {
          System.out.println(a);
      }
  }

  public void printAnimals(ArrayList<Cat> list) {
      for( Cat a : list ) {
          System.out.println(a);
      }
  }


  이제 이 메소드에 dogs(ArrayList<Dog>) 객체를 넘겨서 강아지들의 목록을 제대로 찍을 수 있게 됐다.

  여기서 한 가지 알아둘 것은 와일드카드를 사용하면 method의 인자로 넘어온 객체에 대해서 수정을 가할 수 없다는 것이다.

  즉, 아래와 같이 하면 컴파일시에 오류가 발생한다.

  public void printAnimals(ArrayList<Cat> list) {
      list.add(new Dog());
      for( Cat a : list ) {
          System.out.println(a);
      }
  }

 이 Generic을 다음과 같이 사용할 수도 있다.

public final class Pair<A,B> {
    public final A first;
    public final B second;

    public Pair(A first, B second) {
        this.first = first;
        this.second = second;
    }
}



위와 같이 Pair 라는 class를 정의할 때 generic을 사용하면,
아래와 같이, 비슷한 유형의 class를 여러개 생성하지 않고, collection 처럼 사용할 수 있다.

Pair<String, String> pair1 = new Pair<String, String>("Hello", "World");
Pair<File, Boolean> pair2 = new Pair<File, Boolean>(new File("C:\\"), false);
Pair<String, Integer> pair3 = new Pair<String, Integer>("Won", 1000);




  팁!

  public void doIt(ArrayList<? extends Animal> animals1, ArrayList<? extends Animal> animals2) {
      ....
  }

  는 아래와 같이 사용하면 된다.

  public <T extends Animal> void doIt(ArrayList<T> animals1, ArrayList<T> animals2) {
      ....
  }


@ 실행 소스

# Animal.java
  public abstract class Animal {
      pubilc void eat() {
      }
  }

  # Dog.java
  public class Dog extends Animal {
      public void bark() {
   }
  }

  # Cat.java
  public class Cat extends Animal {
      public void meow() {
   }
  }

  # TestGenerics1.java
  import java.util.ArrayList;

  public class TestGenerics2 {

      public void go() {

           ArrayList<Animal> animals = new ArrayList<Animal>();
           animals.add(new Dog());
           animals.add(new Cat());
           animals.add(new Dog());

           ArrayList<Dog> dogs = new ArrayList<Dog>();
            dogs.add(new Dog());
            dogs.add(new Dog());
            dogs.add(new Dog());

            takeAnimals(animals);
            takeAnimals(dogs);
      }

      // public void takeAnimals(ArrayList<? extends Animal> animals) {
      public <T extends Animal> void takeAnimals(ArrayList<T> animals) {
            // wildcard를 사용하면 아래처럼 method 매개변수에 의해 참조되는 목록에 손상이 갈 만한 작업을 할 수 없습니다.
            // animals.add(new Dog());
            for(Animal a: animals ) {
                  a.eat();
            }
      }

      public static void main(String[] args) {
            new TestGenerics2().go();
      }
  }

'그거 > Java' 카테고리의 다른 글

Java Anti-Pattern  (2) 2007.08.20
JDK 5.0의 새로운 기능 Annotation  (0) 2007.08.14
java Collection 들  (0) 2007.08.10
객체의 hashcode에 대한 고찰  (0) 2007.08.09
The Factory Method Pattern - Design Patterns in Java -  (1) 2007.05.30
:
Posted by 뽀기