pungjoo

작성중 - unmodifiable 본문

JAVA

작성중 - unmodifiable

pungjoo.kim 2010.01.11 19:13
0. 들어가면서
Collections class에는 unmodifiable류의 method가 존재합니다. 즉, 특정상황에 return되는 객체의 특정 method는 사용하지 못 하도록 강제하고 싶을 때 사용합니다. 

1. 준비 운동
package info.yeonwoo.edu;

import java.util.ArrayList;
import java.util.List;

public class WarmingUp {

    private static List<String> getData() {

         ArrayList<String> data = new ArrayList<String>();
         data.add("pungjoo");
         data.add("siyeon");
         data.add("siwoo");

         return data;

    }

    public static void main(String[] args) {

         List<String> data = getData();
         data.add("jihyun");

         System.out.println( data);
    }

}

결과는
[pungjoo, siyeon, siwoo, jihyun]

그럼 위 붉은 색 LINE을... 이렇게~~~~~~~
package info.yeonwoo.edu;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class WarmingUp {

     private static List<String> getData() {

          ArrayList<String> data = new ArrayList<String>();
          data.add("pungjoo");
          data.add("siyeon");
          data.add("siwoo");

          return Collections.unmodifiableList(data);

     }

     public static void main(String[] args) {

          List<String> data = getData();
          data.add("jihyun");

          System.out.println(data);
     }

}

결과는
Exception in thread "main" java.lang.UnsupportedOperationException
      at java.util.Collections$UnmodifiableCollection.add(Collections.java:1018)
      at info.yeonwoo.edu.WarmingUp.main(WarmingUp.java:23)

지원하지 않는 ~~


2. 단순히 생각해 보면 다음과 같이 해 볼 수 있겠죠.

뼈대를 만들어 봅시다..
package info.yeonwoo.edu;

public class Foo {

     private String name;

     public String getName() {

          return name;

     }

     public void setName(String name) {

          this.name = name;

     }

}


뼈대를 실행해 봅시다.
package info.yeonwoo.edu;

public class Bar {

    public static Foo getData() {

        Foo foo = new Foo();
        foo.setName("pungjoo");

        return foo;

     }

     public static void main(String[] args) {

          Foo foo = getData();
          System.out.println( foo.getName());

          foo.setName("siyeon");
          System.out.println( foo.getName());

     }

}

결국은 붉은 색 LINE을 어떻게하면 될 듯 한데...

음 단순하게 이런 방식은 어떨까?
public static Foo getData() {

     final Foo foo = new Foo();
     foo.setName("pungjoo");

     Foo ret = new Foo() {

          @Override
          public void setName(String name) {
               throw new UnsupportedOperationException();
          }

          @Override
          public String getName() {
               return foo.getName();
          }
     };


     return ret;

}

결과
pungjoo
Exception in thread "main" java.lang.UnsupportedOperationException
     at info.yeonwoo.edu.Bar$1.setName(Bar.java:14)
     at info.yeonwoo.edu.Bar.main(Bar.java:32)

원하는 결과는 나왔으나 모든 class의 method를 override를 할 수는 없는 노릇이고...


어쩌구 저쩌구 얼씨구 절씨구~~~~


proxy?.. ( http://pungjoo.tistory.com/17 )

proxy를 사용하기 위해서는 기본조건이 객체는 항상 interface를 사용해야 합니다.  따라서 Foo class를 FooImpl로 변경하고 Foo은 interface화 합니다. 

package info.yeonwoo.edu;

public interface Foo {

     public String getName();

     public void setName(String name);

}

package info.yeonwoo.edu;

public class FooImpl implements Foo {

     private String name;

     @Override
     public String getName() {

        return name;

     }

     @Override
     public void setName(String name) {

          this.name = name;

     }

}



3. 이런건 어떨까?

package info.yeonwoo.edu;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ObjectUnModify implements
InvocationHandler
InvocationHandler {

     private Object obj = null;

     private ObjectUnModify(Object obj) {
          this.obj = obj;
     }

     @Override
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

          if (method.getName().startsWith("set")) {
               throw new UnsupportedOperationException();
          }

         Method mm = obj.getClass().getMethod(method.getName(), method.getParameterTypes());
         return mm.invoke(obj, args);

     }

     @SuppressWarnings( { "hiding", "unchecked" } )
     final public static <T extends Object>T wrap(T obj) {

          return (T) Proxy.newProxyInstance(
                              obj.getClass().getClassLoader(),
                              obj.getClass().getInterfaces(),
                              new ObjectUnModify(obj));

     }

}

이쯤에서 Test를 해 봐야겠지요?
package info.yeonwoo.edu;

public class Bar {

     public static Foo getData() {

          Foo foo = new FooImpl();
          foo.setName("pungjoo");

          return ObjectUnModify.wrap(foo);

     }

     public static void main(String[] args) {

          Foo foo = getData();
          System.out.println( foo.getName());

          foo.setName("siyeon");
          System.out.println( foo.getName());

     }

}

결과는
pungjoo
Exception in thread "main" java.lang.UnsupportedOperationException
at info.yeonwoo.edu.ObjectUnModify.invoke(ObjectUnModify.java:22)
at $Proxy0.setName(Unknown Source)
at info.yeonwoo.edu.Bar.main(Bar.java:19)

어쩌구 저쩌구 해서 저쩌구 어쩌구 이러다 저렇다~~

@
0 Comments
댓글쓰기 폼