'Java'에 해당되는 글 15건

  1. 2015.09.02 자바 형변환
  2. 2015.08.17 Java Calendar로 년월일 얻기
  3. 2015.07.16 Java Serialization 알자 ; 퍼옴
  4. 2015.06.04 String 비교
  5. 2015.05.27 String, StringBuffer, StringBuilder
  6. 2015.04.27 java assert 선언문
  7. 2015.04.08 java StringTokenizer
  8. 2015.04.06 자바 Generic 알아보기
  9. 2015.03.23 various Singleton
  10. 2015.03.19 {JAVA} Enum 열거형
  11. 2015.03.16 자바 동기화 syncronized
  12. 2015.03.06 JNI란
  13. 2015.02.24 java tool IntelliJ
  14. 2015.01.13 자바 메이븐
  15. 2014.03.18 디자인패턴; Singleton

자바 형변환

Java 2015. 9. 2. 17:16

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
 
// int to String
String str = Integer.toString(i);
String str = "" + i;
 
 
// String to int
int i = Integer.parseInt(str);
int i = Integer.valueOf(str).intValue();
 
 
// double to String
String str = Double.toString(d);
 
 
// long to String
String str = Long.toString(l);
 
 
// float to String
String str = Float.toString(f);
 
 
// String to double
double d = Double.valueOf(str).doubleValue();
 
 
// String to long
long l = Long.valueOf(str).longValue();
long l = Long.parseLong(str);
 
 
// String to float
float f = Float.valueOf(str).floatValue();
 
 
// decimal to binary
String binstr = Integer.toBinaryString(i);
 
 
// decimal to hexadecimal
String hexstr = Integer.toString(i, 16);
String hexstr = Integer.toHexString(i);
Integer.toHexString( 0x10000 | i).substring(1).toUpperCase());
 
 
// hexadecimal(String) to int
int i = Integer.valueOf("B8DA3", 16).intValue();
int i = Integer.parseInt("B8DA3", 16);
 
 
// ASCII Code to String
String char = new Character((char)i).toString();
 
 
// Integer to ASCII Code
int i = (int) c;
 
 
// Integer to boolean
boolean b = (i != 0);
 
 
// boolean to Integer
int i = (b)? 1 : 0;
 
 
cs


:

Java Calendar로 년월일 얻기

Java 2015. 8. 17. 15:11
1
2
3
4
5
6
7
8
9
10
11
12
13
import java.util.Calendar;
 
public class Main {
 
  public static void main(String[] args) {
    Calendar now = Calendar.getInstance();
    // 
    System.out.println("Current Year is : " + now.get(Calendar.YEAR));
    // month start from 0 to 11
    System.out.println("Current Month is : " + (now.get(Calendar.MONTH) + 1));
    System.out.println("Current Date is : " + now.get(Calendar.DATE));
  }
}
cs





:

Java Serialization 알자 ; 퍼옴

Java 2015. 7. 16. 10:56


Java Serialization 알자

이 자료는 자바랜드(www.javaland.co.kr)의 박정기께서 기고하신 내용입니다. 

 

Java Serialization맛보기

Java Serializatoin은 자바 객체를 저장하거나 전송하기 위하여 자바 객체의 코드를 다시 복원가능한 형태의 Stream으로 직렬화 시켜주는 것을 말한다. 

 

가장 간단한 형태부터 시작해서 자바 시리얼라이제이션의 예를 살펴 보도록 하겠다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<< swrite.java>> 
import java.lang.*; 
import java.io.*; 
import java.util.*; 
 
class swrite 
{ 
    public static void main(String args[]) 
    { 
       try{       
        FileOutputStream f = new FileOutputStream("tmp"); 
        ObjectOutput s = new ObjectOutputStream(f); 
        s.writeObject("Today"); 
        s.writeObject(new Date()); 
        s.flush(); 
       } 
         catch(IOException e) { }     
         System.out.println("Today"); 
         System.out.println(new Date()); 
    } 
} 
cs

 

 

위의 프로그램은 File Stream을 열어서 tmp라는 파일에 2개의 객체("Today"라는 String 객체와 Date 객체)를 저장하고 있다.  

여기서 객체저장을 위해 writeObject라는 메쏘드가 사용되고 있다는 것을 알 수 있다. 

 

위의 프로그램을 실행하면 2 객체가 시리얼라이제이션이 일어나서 다시 복원가능한 형태로되어 직렬화되어

tmp라는 파일로 저장된다. 

 

객체를 파일로 저장하다니? 얼마나 놀라운가? 

(제대로 다시 복원만 된다면...) 

 

자! 그럼 tmp 파일에서 객체를 살려보자!!! 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<< sread.java >> 
 
import java.lang.*; 
import java.io.*; 
import java.util.*; 
 
class sread 
{ 
    public static void main(String args[]) 
    { 
         try {       
           FileInputStream in = new FileInputStream("tmp"); 
           ObjectInput s = new ObjectInputStream(in); 
           String today = (String)s.readObject(); 
           Date date = (Date)s.readObject(); 
            
           System.out.println(today); 
           System.out.println(date); 
         } 
         catch(IOException e) { }     
         catch(ClassNotFoundException e) {} 
    } 
} 
cs

 

위의 파일은 아까 저장한 tmp파일에서 객체를 복원하여  

today와 date가 저장 직전의 상태로 복원되었다. 

여기서 readObject라는 메쏘드가 사용되었음을 알 수 있다. 

 

객체를 저장한 tmp 파일은 직렬화되어있으므로  

그냥 내용을 사용자가 알 수 없다. 

하지만 2 객체를 훌륭하게 저장하였다는 것을 알 수 있다.

 

Java Serializatoin의 개념 이해

앞의 예제는 Java Serializatoin의 맛빼기였다. 

그냥 대충 돌아가는 것만 보여준 것이지 개념상  

부족한 내용이 많다. 

 

좀더 심화된 내용으로 Java Serialization을 제대로 이해해 보자! 

 

Java Object Serialization은 자바 객체를 저장 또는 전송을 위하여 자바 코드를 다시 복원 가능한 byte stream 형태로 변환시켜 준다. 이 직렬화 과정을 자세히 말하면 

객체가 다시 원상태로 복원되기 위해서는 객체 내부의 

data들의 reference가 잘 정리되어야 있어야 한다.  

이러한 과정은 직렬화를 통하여 object reference의 tree 

즉, object graph를 형성하므로써 가능하다. 

이 graph 정보를 이용해서 객체를 다시 복원할 수 있는 것이다. 

 

이제 객체를 byte stream으로 변환되는 과정을 marshaling이라 부르고, 반대로 stream에서 객체로 역변환하는 과정을 unmarshaling이라고 한다. 

 

또한 객체가 안전하게 직렬화되기 위해서는 

해당 클래스가 Serializable 인터페이스를 imeplements하고 있어야만 한다. 

 

앞의 강좌 1의 예제에서는... 

알다시피 String 클래스와 Date 클래스 모두 API 레퍼런스를 보면 이미 Serializable 인터페이스를 imeplements하고 있을 확일할 수 있다. 

 

자! 그럼... 

 

이번엔 사용자가 정의한 클래스를 직렬화시켜서 

파일로 저장하고 다시 복원하는 예제를 보도록 하자! 

 

먼저 전송할 사용자가 만든 Test 클래스를 다음과 같이 만든다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
<< Test.java >> 
 
public class Test implements java.io.Serializable 
{ 
   public String str; 
   public transient int ivalue; 
   public Test(String s, int i) 
   { 
       str = s; 
       ivalue = i; 
   } 
} 
cs

 

당연히 java.io.Serializable 인터페이스를 implements하고 있어야 한다. 

위에서 Test 클래스에 멤버변수로 String 타입의 str과 int 타입의 ivalue가 있음을 볼 수 있다. 

그런데 이기서 transient 키워드에 주목하자! 

transient 키워드는 앞에 지정하면 지정된 항목 내용은  

자바 시리얼라이제이션에서 제외된다.  

즉, 직렬화가 이루어질때 사용자가 문제의 소지가 있는 변수나 메쏘드를 제외시킬 수 있도록 해주는 것이다. 

 

그럼 Test 클래스를 직렬화하여 파일로 저장해보자! 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<< write.java >> 
 
import java.io.*; 
 
public class write 
{ 
    public static void main(String args[])  
    { 
        try{   
            FileOutputStream fos = new FileOutputStream("file.out"); 
            ObjectOutputStream oos = new ObjectOutputStream(fos); 
            oos.writeObject(new Test("testing", 37)); 
            oos.flush(); 
            fos.close(); 
        } 
        catch(Throwable e)  
        { 
            System.err.println(e); 
        }    
    } 
}
cs

 

위의 소스는 Test 객체를 file.out이라는 이름의 파일로 저장할 것이다. 

역시 writeObject를 사용했고, 초기 값으로 "testing" 이라는 문자열과 37의 값을 지정했다. 

 

자! 그럼 file.out 파일에서 Test 객체로 복원시켜 보자! 

 

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
<< read.java >> 
 
import java.io.*; 
 
public class read 
{ 
   public static void main(String args[]) 
   { 
       Test testobj = null; 
       try 
       { 
           FileInputStream fis = new FileInputStream("file.out"); 
           ObjectInputStream ois = new ObjectInputStream(fis); 
           testobj = (Test)ois.readObject(); 
           fis.close(); 
       } 
       catch(Throwable e) 
       { 
           System.err.println(e); 
       } 
        
       System.out.println(testobj.str); 
       System.out.println(testobj.ivalue); 
   } 
} 
cs

 

위의 소스를 컴파일하여 실행시켜 보면 

file.out 파일에서 readObject 메쏘드를 사용해서 Test 객체를 복원해 낸다. 

 

결과를 출력해보면 다음과 같다!!! 

 

testing 

0 

 

여기서 testobj.str의 값은 저장하기 이전 상태 그대로지만 testobj.ivalue의 값은 처음에 37로 지정했는데 0으로 출력되었다. 

 

이것은 test 클래스에서 transient 키워드가 지정되었기 때문에 시리얼라이제이션에서 제외되었기 때문에 본래 값을 보존할 수 없었던 것이다.

 

Java Object Serializatoin

Java Object Serializatoin의 3회 강좌를 시작한다. 

이번에는 객체를 소켓을 통해서 전송하는 방법에 대해서 다루겠다. 

이때 주의해할 점이 있는데... 이것은 

예제를 통해서 공부해 보도록 하겠다. 

 

먼저 전송할 객체 클래스를 다음과 같이 만들었다고 하자!  

 

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
<< MyObject.java>> 
 
import java.io.*; 
 
public class MyObject implements Serializable  
{ 
   String name; 
   int count; 
 
   MyObject()    // 컨스트럭터 
   { 
       setName(); 
   } 
 
   public void setName()  
   { 
       count++; 
       name = "MyObject " + count; 
   } 
                                                                  
   public String toString()  
   {  
       return name;  
   } 
} 
cs

 

==== 

 

역시... Serializable 인터페이스를 implements하고 있으며... 변수로 name과 count를 가지고 있다. 

컨스트럭터에서 setName() 메쏘드를 호출하여 count를 증가시키고 name의 String에도 숫자가 추가되고 있다. 

 

그러면 위의 객체를 스트림을 통하여 소켓으로 전송하기위하여 먼저 서버를 만들어보자! 

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<< JabberServer.java >> 
 
import java.io.*; 
import java.net.*; 
 
public class JabberServer  
{  
    static final int port = 8080; 
    public static void main(String[] args )  
    { 
        try  
        {  
             MyObject o = new MyObject(); 
             ServerSocket s = new ServerSocket(port); 
             System.out.println("Server Started: " + s); 
             Socket socket = s.accept(); 
             System.out.println("Connection accepted,
                                         socket: " + socket); 
             ObjectOutputStream ToClient = new ObjectOutputStream(socket.getOutputStream()); 
             DataInputStream FromClient = new DataInputStream(socket.getInputStream()); 
 
             while (o.count<11)  
             {  
                  System.out.println("writing " + o); 
                  o.setName();  
                  /**
                    Object reference를 reset한다. 
                    (이 부분이 포인트) 
                    이것을 안하면 첫번째 전송한 객체의  
                    reference로  계속 전송된다.
                    그래서 갱신된 data가 반영되지 못하는
                    현상이 생긴다. 
                  */
                  ToClient.reset();  
                  ToClient.writeObject(o); 
                  System.out.print("trying to received acknowledgement ... "); 
                  System.out.println("acknowledgement: " + FromClient.readInt());  
                  System.out.println("succeeded"); 
             } 
             System.out.println("closing..."); 
             ToClient.close(); 
             socket.close(); 
        }  
        catch(Exception e)  
        { 
             e.printStackTrace(); 
        }  
   } 
}
cs

 

=== 

 

위 서버 프로그램에서는 서버 소켓을 8080 포트로 열어놓고 클라언트를 기다리다가 클라이언트가 억셉트되면 계속 동작하게 되어있다. 

 

계속 설명하기 전에... 클라이언트 프로그램도 같이 보도록 하자! 

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<< JabberClient.java >> 
 
import java.net.*; 
import java.io.*; 
 
public class JabberClient 
{ 
   static final int port = 8080; 
   public static void main(String args[])  
   { 
       MyObject o; 
       try  
       { 
           InetAddress addr = InetAddress.getByName(null); 
           System.out.println("addr = " + addr); 
           Socket socket = new Socket(addr, port); 
           System.out.println("socket = " + socket); 
           ObjectInputStream FromServer = new 
           ObjectInputStream(socket.getInputStream()); 
           DataOutputStream ToServer = new 
           DataOutputStream(socket.getOutputStream()); 
 
           int i=0;  
           while(true)  
           { 
               o = (MyObject)FromServer.readObject(); 
               System.out.print("trying to send acknowledgement ... "); 
               Thread.sleep(500); 
               ToServer.writeInt(i++); 
               System.out.println("succeeded"); 
               System.out.println(o); 
           } 
      }  
      catch (EOFException f)  
      { 
           System.exit(0); 
      }  
      catch(Exception e)  
      { 
           e.printStackTrace(); 
      } 
  } 
}  
cs

 

===  

 

소켓이 맺어진 후에... 

 

서버에서 MyObject 객체를 생성하면 컨스트럭터에의해 카운트가 1이 된다. 

그후 setName() 메쏘드를 호출하고 나면 카운트가 2가 되고  이것을 스트림으로 바꾸어 객체를 전송하게 된다. 

 

클라이언트는 전송된 객체를 받아 ACK 성공 메시지를 뿌리고 카운트 값을 찍는다. 

 

그후 서버에서 setName() 메쏘드를 다시 호출하여 객체의 카운트 상태값을  하나 증가시켜 3으로 만든후 객체를 스트림으로 전송한다. 

 

클라이언트는 두번째 객체를 받아 ACK 성공 메시지를 뿌리고 카운트 값을 찍는다. 

이때 카운트 값이 갱신된 3값으로 찍혀야 하는데... 

여전히 2로 찍혀져 나온다? 

 

왜일까???    

 

이것은 자바의 버그가 아니다. 

 

이것은 자바 시리얼라이제이션에서는 

처음 전송한 객체의 object reference를 인위적으로

reset시켜 주지 않으면 객체의 상태가 바뀌더라도 전송되는 객체의 object reference는  처음 전송한 객체의 object reference로 계속 가지게 되므로  이와 같은 현상이 발생한다. 

 

이문제를 해결하려면... 

객체를 스트림으로 전송하기 전에... 

reset() 메쏘드를 통하여 같은 object reference를 사용하지 않도록 리셋시켜주어야 한다. 

 

즉, 

ToClient.reset(); 부분에 대한 이해가 이번 강좌의 포인트이다. 

이부분이 있고, 없고의 차이를 반드시 이해하기 바란다. 

 

객체를 소켓으로 계속 전송하게 될 경우... 

실수하면 위와같은 버그아닌 오류에 봉착하기 쉽다. 

 

그럼 이상으로 3회 강좌를 마친다.

 

 

펌 : http://www.javaland.co.kr/





:

String 비교

Java 2015. 6. 4. 10:26

문자열을 비교하는 기본적인 방법은

String str1 = "abc";

String str2 = "abc";


if(str==str2)

{

//

}


equals

public boolean equals(Object anObject)


if(str1.equals(str2))

{

// 문자열 비교

}


equalsIgnoreCase

public boolean equalsIgnoreCase(String anotherString)


if(str1.equalsIgnoreCase(str2))

{

// 대소문자에 상관없이 두 문자열이 같으면 true를 리턴

}

:

String, StringBuffer, StringBuilder

Java 2015. 5. 27. 14:14


StringBuffer, StringBuilder 는 String을 char과 concat 할 경우에 유용하게 사용할 수 있는데,

StringBuffer 는 멀티스레드에서 동기화를 지원한다.


복잡한 경우에 StringBuffer, StringBuilder의 활용이 의미가 있겠으나,

단순한 경우에는 String을 + 를 통해 "a" + 1 + "b" 로 직접 연결해 사용해도 상관없다.

JDK 1.5 이후부터는 StringBuilder로 컴파일되도록 변경되었기 때문에 + 를 통한 String 연결로 인한 성능저하는 없다.


http://www.slipp.net/questions/271

:

java assert 선언문

Java 2015. 4. 27. 23:34

자바 1.4(and 5.0) 이상부터 지원하는 디버깅 코드.


두가지 방식으로 사용할 수 있는데,


1. assert [boolean 식]

asser(num > 0);


2. assert [boolean 식] : [표현식];

assert(num>0) : "that's it!";


boolean이 참이면 프로그램을 계속 돌리고 아니면 AssertionError를 발생시킨다.


@ 컴파일

기존의 컴파일 방식과 동일하게 진행되며 error code 를 검출하고 싶다면 실행 시 -ea 옵션을 지정하여 실행한다.

ex) java -ea TestAssert


@ 주의

객체의 상태를 변화시키는 작업은 지양하는 것이 좋다. 에러검출용 코드로만 이용하도록.


참고는 여기서, http://zion437.tistory.com/128

:

java StringTokenizer

Java 2015. 4. 8. 11:44

String을 token 단위로 끊어주는 클래스.

string을 StringTokenizer 로 생성하여 사용할 수 있음.

기본적으로 공백을 token으로 인식하고 특정문자를 사용하여 나눌수도 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.StringTokenizer;
 
public class TestToken {
    public static void main(String[]args){
        try{
            // 기본적으로 공백을 token으로 인식
            String str = "2015 04 08";
            StringTokenizer st = new StringTokenizer(str);
            
            System.out.println("test- " + st.nextToken());
            System.out.println("test- " + st.nextToken());
            System.out.println("test- " + st.nextToken());
        }catch(Exception e){
            
        }
    }
}
 
cs



:

자바 Generic 알아보기

Java 2015. 4. 6. 23:46

자바의 generic type은 형의 안정성을 보장한다.


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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package com.java.collection;
 
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
 
class Mountain{
    String name;
    int height;
    
    Mountain(String n, int h){
        this.name=n;
        this.height=h;
    }
    
    public String getName(){
        return this.name;
    }
    
    public int getHeight(){
        return this.height;
    }
    
    public String toString(){
        return this.name + " " + this.height;
    }
}
 
public class SortMountains {
    LinkedList<Mountain> mtn = new LinkedList<Mountain>();
    
    class NameCompare implements Comparator<Mountain>{
        @Override
        public int compare(Mountain one, Mountain two){
            return one.getName().compareTo(two.getName());
        }
    }
    
    class HeightCompare implements Comparator<Mountain>{
        @Override
        public int compare(Mountain one, Mountain two){
            // 양수 내림차순, 음수 올림차순 
            return one.getHeight() - two.getHeight();
        }
    }
    
    public static void main(String [] args){
        new SortMountains().go();
    }
    
    public void go(){
        mtn.add(new Mountain("Longs", 14255));
        mtn.add(new Mountain("Elbert", 14433));
        mtn.add(new Mountain("Maroon", 14156));
        mtn.add(new Mountain("Castle", 14265));
        System.out.println("as entered:\n" + mtn);
        
        NameCompare nc = new NameCompare();
        Collections.sort(mtn, nc);
        System.out.println("by name;\n" + mtn);
        
        HeightCompare hc = new HeightCompare();
        Collections.sort(mtn, hc);
        System.out.println("by height;\n" + mtn);
    }
}
cs


:

various Singleton

Java 2015. 3. 23. 16:17
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
/*
  More tests of various singleton implementations
  last update: Mon Mar 26 20:19:39 2001  Doug Lea  (dl at gee)
*/
 
 
class TSS extends Thread {
 
  static abstract class Singleton {
    // a  field and method to prevent some compiler optimizations
    int aField = System.identityHashCode(this);
    int aMethod(int i) { return (i % 17) != 0 ? aField: i; }
  }
 
  static class EagerSingleton extends Singleton {
    static final EagerSingleton theInstance = new EagerSingleton();
    static EagerSingleton getInstance() {
      return theInstance;
    }
  }
 
 
  static class SynchedSingleton extends Singleton {
    static SynchedSingleton theInstance;
    static synchronized SynchedSingleton getInstance() {
      if (theInstance == null) 
        theInstance = new SynchedSingleton();
      return theInstance;
    }
  }
 
  static class ThreadLocalSingleton extends Singleton {
    static final ThreadLocal perThreadInstance = new ThreadLocal();
    static final Object lock = new Object();
    static ThreadLocalSingleton theInstance;
 
    static ThreadLocalSingleton getInstance() {
      ThreadLocalSingleton instance = (ThreadLocalSingleton)(perThreadInstance.get());
      if (instance == null) {
 
        synchronized(lock) {
          instance = theInstance;
          if (instance == null) 
            instance = theInstance = new ThreadLocalSingleton();
        }
        // copy global to per-thread
        perThreadInstance.set(instance);
      }
      return instance;
    }
  }
 
  static class SimulatedThreadLocalSingleton extends Singleton {
    static SimulatedThreadLocalSingleton theInstance;
    static final Object lock = new Object();
    static final Object key = new Object();
 
    static Singleton getInstance() {
      TSS t = (TSS)(Thread.currentThread());
      Singleton instance = (Singleton)(t.threadLocalHashtable.get(key));
      if (instance == null) {
 
        synchronized(lock) {
          instance = theInstance;
          if (instance == null) 
            instance = theInstance = new SimulatedThreadLocalSingleton();
        }
        // copy global to per-thread
        t.threadLocalHashtable.put(key, instance);
      }
      return instance;
    }
  }
 
 
  static class VolatileSingleton extends Singleton {
    static final Object lock = new Object();
    static volatile VolatileSingleton theInstance;
 
    static VolatileSingleton getInstance() {
      VolatileSingleton instance = theInstance;
      if (instance == null) {
        synchronized(lock) {
          instance = theInstance;
          if (instance == null) 
            instance = theInstance = new VolatileSingleton();
        }
      }
      return instance;
    }
  }
 
  static class DirectThreadFieldSingleton extends Singleton {
    static DirectThreadFieldSingleton theInstance;
    static final Object lock = new Object();
 
    static Singleton getInstance(TSS t) {
      Singleton instance = t.singleton;
      if (instance == null) {
 
        synchronized(lock) {
          instance = theInstance;
          if (instance == null) 
            instance = theInstance = new DirectThreadFieldSingleton();
        }
        // copy global to per-thread
        t.singleton = instance;
      }
      return instance;
    }
  }
 
 
 
  static class ThreadFieldSingleton extends Singleton {
    static final Object lock = new Object();
    static ThreadFieldSingleton theInstance;
 
    static Singleton getInstance() {
      TSS t = (TSS)(Thread.currentThread());
      Singleton instance = t.singleton;
      if (instance == null) {
 
        synchronized(lock) {
          instance = theInstance;
          if (instance == null) 
            instance = theInstance = new ThreadFieldSingleton();
        }
        // copy global to per-thread
        t.singleton = instance;
      }
      return instance;
    }
  }
 
 
 
  static final int ITERS = 1000000;
  static final int NTHREADS = 8;
 
  static int total; // accumulate calls to aMethod, to prevent overoptimizing
 
 
  final IDHashMap threadLocalHashtable = new IDHashMap(8);
  Singleton singleton;
  int mode;
  TSS(int md) { mode = md; }
 
  public void run() {
    int sum = 0; // to prevent optimizations
 
    if (mode == 0) {
      for (int i = 0; i < ITERS; ++i) {
        sum += EagerSingleton.getInstance().aMethod(i);
      }
    }
    else if (mode == 1) {
      for (int i = 0; i < ITERS; ++i) {
        sum += ThreadLocalSingleton.getInstance().aMethod(i);
      }
    }
    else if (mode == 2) {
      for (int i = 0; i < ITERS; ++i) {
        sum += SimulatedThreadLocalSingleton.getInstance().aMethod(i);
      }
    }
    else if (mode == 3) {
      for (int i = 0; i < ITERS; ++i) {
        sum += VolatileSingleton.getInstance().aMethod(i);
      }
    }
    else if (mode == 4) {
      for (int i = 0; i < ITERS; ++i) {
        sum += SynchedSingleton.getInstance().aMethod(i);
      }
    }
    else if (mode == 5) {
      for (int i = 0; i < ITERS; ++i) {
        sum += DirectThreadFieldSingleton.getInstance(this).aMethod(i);
      }
    }
    else if (mode == 6) {
      for (int i = 0; i < ITERS; ++i) {
        sum += ThreadFieldSingleton.getInstance().aMethod(i);
      }
    }
 
    total += sum;
  }
 
  public static void main(String[] args) {
 
    Thread[] threads = new Thread[NTHREADS];
 
    for (int reps = 0; reps < 3; ++reps) {
 
      for (int i = 0; i < NTHREADS; ++i) 
        threads[i] = null;
      System.gc();
 
      for (int mode = 0; mode < 7; ++mode) {
 
        if (mode == 0) 
          System.out.print("Eager:            ");
        else if (mode == 1) 
          System.out.print("ThreadLocal:      ");
        else if (mode == 2)
          System.out.print("SimThreadLocal:   ");
        else if (mode == 3)
          System.out.print("Volatile (DCL):   ");
        else if (mode == 4)
          System.out.print("Synch:            ");
        else if (mode == 5)
          System.out.print("Direct Field:     ");
        else if (mode == 6)
          System.out.print("Thread Field:     ");
 
        long startTime = System.currentTimeMillis();
 
        for (int i = 0; i < NTHREADS; ++i) 
          threads[i] = new TSS(mode);
        
        for (int i = 0; i < NTHREADS; ++i) 
          threads[i].start();
        
        try {
          for (int i = 0; i < NTHREADS; ++i) 
            threads[i].join();
        }
        catch (InterruptedException ie) {
          System.out.println("Interrupted");
          return;
        }
 
        long elapsed = System.currentTimeMillis() - startTime;
        System.out.println(elapsed + "ms");
 
        if (total == 0) // ensure total is live to avoid optimizing away
          System.out.println("useless number = " + total);
        
      }
    }
  }
}
 
 
/*
  Renamed and hacked version of 1.4 IdentityHashMap so can test on pre-1.4
*/
 
class IDHashMap {
    /**
     * The initial capacity used by the no-args constructor.
     * MUST be a power of two.  The value 32 corresponds to the
     * (specified) expected maximum size of 21, given a load factor
     * of 2/3.
     */
    private static final int DEFAULT_CAPACITY = 32;
 
    /**
     * The minimum capacity, used if a lower value is implicitly specified
     * by either of the constructors with arguments.  The value 4 corresponds
     * to an expected maximum size of 2, given a load factor of 2/3.
     * MUST be a power of two.
     */
    private static final int MINIMUM_CAPACITY = 4;
 
    /**
     * The maximum capacity, used if a higher value is implicitly specified
     * by either of the constructors with arguments.
     * MUST be a power of two <= 1<<29.
     */
    private static final int MAXIMUM_CAPACITY = 1 << 29;
 
    /**
     * Special value used to mark slots as deleted.
     */
    private static final Object DELETED = new Object();
 
    /**
     * Special value used to mark slots as empty.
     */
    private static final Object EMPTY = new Object();
 
    /**
     * The table, resized as necessary. Length MUST Always be a power of two.
     */
    private transient Object[] table;
 
    /**
     * The number of key-value mappings contained in this identity hash map.
     *
     * @serial
     */
    private int size;
 
 
    /**
     * The next size value at which to resize (capacity * load factor).
     */
    private transient int threshold;
 
    /**
     * Constructs a new, empty identity hash map with a default expected
     * maximum size (21).
     */
    public IDHashMap() {
        init(DEFAULT_CAPACITY);
    }
 
 
    /**
     * Constructs a new, empty map with the specified expected maximum size.
     * Putting more than the expected number of key-value mappings into
     * the map may cause the internal data structure to grow, which may be
     * somewhat time-consuming.
     *
     * @param expectedMaxSize the expected maximum size of the map.
     * @throws IllegalArgumentException if <tt>expectedMaxSize</tt> is negative
     */
    public IDHashMap(int expectedMaxSize) {
        if (expectedMaxSize < 0)
            throw new IllegalArgumentException("expectedMaxSize is negative");
 
        init(capacity(expectedMaxSize));
    }
 
    /**
     * Returns the appropriate capacity for the specified expected maximum
     * size.  Returns the smallest power of two between MINIMUM_CAPACITY
     * and MAXIMUM_CAPACITY, inclusive, that is greater than
     * (3 * expectedMaxSize)/2, if such a number exists.  Otherwise
     * returns MAXIMUM_CAPACITY.  If (3 * expectedMaxSize)/2 is negative, it
     * is assumed that overflow has occurred, and MAXIMUM_CAPACITY is returned.
     */
    private int capacity(int expectedMaxSize) {
        // Compute min capacity for expectedMaxSize given a load factor of 2/3
        int minCapacity = (3 * expectedMaxSize)/2;
 
        // Compute the appropriate capacity
        int result;
        if (minCapacity > MAXIMUM_CAPACITY || minCapacity < 0) {
            result = MAXIMUM_CAPACITY;
        } else {
            result = MINIMUM_CAPACITY;
            while (result < minCapacity)
                result <<= 1;
        }
        return result;
    }
 
    /**
     * Initialize object to be an empty map with the specified initial
     * capacity, which is assumed to be a power of two between
     * MINIMUM_CAPACITY and MAXIMUM_CAPACITY inclusive.
     */
    private void init(int initCapacity) {
        // assert (initCapacity & -initCapacity) == initCapacity; // power of 2
        // assert initCapacity >= MINIMUM_CAPACITY;
        // assert initCapacity <= MAXIMUM_CAPACITY;
 
        threshold = (initCapacity * 2)/3;
        table = new Object[2 * initCapacity];
        for (int i = 0; i < table.length; i += 2)
            table[i] = EMPTY;
    }
 
    /**
     * Returns the number of key-value mappings in this identity hash map.
     *
     * @return the number of key-value mappings in this map.
     */
    public int size() {
        return size;
    }
 
    /**
     * Returns <tt>true</tt> if this identity hash map contains no key-value
     * mappings.
     *
     * @return <tt>true</tt> if this identity hash map contains no key-value
     *         mappings.
     */
    public boolean isEmpty() {
        return size == 0;
    }
 
    /**
     * Return index for Object x given table size len, where len is a power of
     * two. 
     */
    private static int hash(Object x, int len) {
        int h = System.identityHashCode(x);
        return h & (len-2);
    }
 
    /**
     * Returns the value to which the specified key is mapped in this identity
     * hash map, or <tt>null</tt> if the map contains no mapping for
     * this key.  A return value of <tt>null</tt> does not <i>necessarily</i>
     * indicate that the map contains no mapping for the key; it is also
     * possible that the map explicitly maps the key to <tt>null</tt>. The
     * <tt>containsKey</tt> method may be used to distinguish these two
     * cases.
     *
     * @param   key the key whose associated value is to be returned.
     * @return  the value to which this map maps the specified key, or
     *          <tt>null</tt> if the map contains no mapping for this key.
     * @see #put(Object, Object)
     */
    public Object get(Object key) {
        int i = hash(key, table.length);
        while (true) {
            Object item = table[i];
            if (item == key) 
                return table[i+1];
            if (item == EMPTY)
                return null;
            if ((i+=2) >= table.length)
                i = 0;
        }
    }
 
    /**
     * Associates the specified value with the specified key in this identity
     * hash map.  If the map previously contained a mapping for this key, the
     * old value is replaced.
     *
     * @param key the key with which the specified value is to be associated.
     * @param value the value to be associated with the specified key.
     * @return the previous value associated with <tt>key</tt>, or
     *           <tt>null</tt> if there was no mapping for <tt>key</tt>.  (A
     *         <tt>null</tt> return can also indicate that the map previously
     *         associated <tt>null</tt> with the specified key.)
     * @see     Object#equals(Object)
     * @see     #get(Object)
     * @see     #containsKey(Object)
     */
    public Object put(Object key, Object value) {
        /*
         * insertionIndex is the index of the first DELETED
         * entry passed over while checking if x is already
         * present. If such a slot exists, we should use it
         * rather than trailing null slot
         */
        int insertionIndex = -1; 
        int i = hash(key, table.length); 
 
        while (true) {
            Object item = table[i];
 
            if (item == EMPTY) {
                if (insertionIndex < 0)
                    insertionIndex = i;
                table[insertionIndex] = key;
                table[insertionIndex+1] = value;
 
                if (++size >= threshold) resize();
                return null;
            } else if (item == key) {
                Object oldValue = table[++i];
                table[i] = value;
                return oldValue;
            } else if (item == DELETED && insertionIndex < 0) {
                insertionIndex = i; 
            }
           if ((i+=2) >= table.length)
                i = 0;
        }
    }
 
    /**
     *  Double the size of the table
     */
    private void resize() {
        int oldTableSize = table.length;
        if (oldTableSize == 2*MAXIMUM_CAPACITY) { // can't expand any further
            if (threshold == MAXIMUM_CAPACITY-1)
                throw new IllegalStateException("Capacity exhausted.");
            threshold = MAXIMUM_CAPACITY-1;  // Gigantic map!
            return;
        }
 
        int newSize = 2 * oldTableSize;
        threshold = (oldTableSize * 2)/3;
 
        Object[] oldTable = table;
        table = new Object[newSize];
        for (int i = 0; i < table.length; i +=2)
            table[i] = EMPTY;
 
        for (int j = 0; j < oldTable.length; j+=2) {
            Object key = oldTable[j];
            if (key != EMPTY && key != DELETED) {
                Object value = oldTable[j+1];
 
                int i = hash(key, table.length);  
                while (table[i] != EMPTY) {
                    if ((i+=2) == table.length)
                        i = 0;
                }
        
                table[i] = key;
                table[i+1] = value;
            }
        }
    }
 
    /**
     * Removes the mapping for this key from this map if present.
     *
     * @param key key whose mapping is to be removed from the map.
     * @return previous value associated with specified key, or <tt>null</tt>
     *           if there was no entry for key.  (A <tt>null</tt> return can
     *           also indicate that the map previously associated <tt>null</tt>
     *           with the specified key.)
     */
    public Object remove(Object key) {
        int i = hash(key, table.length);
        while (true) {
            Object item = table[i];
            if (item == EMPTY) 
                return null;
            else if (item == key) {
                Object oldValue = table[i+1];
                markAsDeleted(i);
                return oldValue;
            }
            if ((i+=2) >= table.length)
                i = 0;
        }
    }
 
 
    /**
     * Mark table[index] as either DELETED or, if possible, EMPTY.
     */
    private void markAsDeleted(int index) {
        /*
         * Because table[index] could have been between two real items
         * without an intervening EMPTY, it must normally be marked as
         * DELETED so that linear probing continues to work. But if it is
         * part of a sequence of DELETEDs ending in a EMPTY, table[index] and
         * other members of the sequence can be set to EMPTY, which will
         * shorten subsequent searches, especially after bursts of
         * removals. It also guarantees that an empty table has no DELETED
         * markers. In practice, this keeps the number of DELETED markers
         * low enough to not hurt search times much in the presence of
         * deletions.
         *
         * Note that the alternative of re-inserting old elements rather
         * than using a DELETED marker cannot be used here because this
         * could re-arrange items in the midst of an iteration.
         */
        --size;
 
        table[index+1] = null; // null out value;
 
        int j = index;
        while (true) { // Traverse starting at next slot after index
            if ((j+=2) == table.length)
                j = 0;
 
            Object item = table[j];
            if (item == EMPTY)           // Found a sequence ending in EMPTY
                break;
 
            else if (item != DELETED) { // no such luck
                table[index] = DELETED;
                return;
            }
        }
 
        while (true) {                   // Run backwards until not DELETED
            if ((j-=2) < 0)
                j = table.length - 2;
 
            if (j == index || table[j] == DELETED)
                table[j] = EMPTY;
            else
                return;
        }
    }
 
    /**
     * Removes all mappings from this map.
     */
    public void clear() {
        for (int i = 0; i < table.length; i+=2)
            table[i] = EMPTY;
        for (int i = 1; i < table.length; i+=2)
            table[i] = null;
        size = 0;
    }
 
 
}
cs


:

{JAVA} Enum 열거형

Java 2015. 3. 19. 15:34

JAVA 와 XML 에서의 문자열 관리하는 방법에는 근본적인 차이가 존재한다.


String Calss 란?
JAVA에서 String 객체내 보관하는 문자열은 유니코드로 변형하여 보관하므로 HTML과 같이 마크업 문자를 입력하고 출력할 때 문제가 발생한다. 따라서 String 객체에 입력되는 문자열은 마크업 문자를 입력하여 사용할 수 없는 문자열인란 의미로 변경금지 문자라 부른다.

CharSequence 란?
반면에 CharSequence 객체내 보관하는 문자열은 같은 String 클래스와 같은 유니코드라 하더라도 마크업 문자를 사용하여 변형과 가공이 가능한 문자열이란 의미로 스타일 문자 또는 연속되는 문자라고 한다.

◆ CharSequence 객체의 제공 Method
  • char charAt(int index) : 인덱스가 가리키는 문자를 반환한다.
  • int length() : CharSequence 객체의 문자수를 반환한다.
  • CharSequence subsequence(int start, int end) : start부터 end까지의 문자를 반환한다.
  • String toString() : CharSequence 객체를 문자열로 반환한다.

◆ XML 문서와 JAVA 프로그램간의 출력하거나 읽을 때 사용 할 수 있도록 XML 버퍼타입을 제공한다.버퍼타입은 Enum 타입으로 지원한다.
  • NORMAL : 디폴트 CharSequence 객체로 반환된다. XML 문서내 문자열은 입력시 소스 문자가 스타일 문자면 스타일 문자로 반환되고 아닌 경우는 일반 String 객체의 문자열로 반환된다.
  • SPANNABLE : 마크업문자를 넣을 수 있는 스타일 문자이다. 항상 스타일 문자로 반환된다.
  • EDITABLE : 편집가능한 스타일 문자이다. EditText는 EDITABLE 속성으로 반환된다.

◆ TextView 클래스에서 제공하는 메서드
  • CharSequence getText()
  • void setText (CharSequence text)
  • void setText (int resid, TextView.BufferType type)
  • void setText (CharSequence text, TextView.BufferType type)

◉String.xml에서 마크업 문자로 작성.
<?xml version=”1.0” encoding=”utf-8”?>
<resources>
    <string name=”styled_text”>기본(Plain), <b>강조 bold</b> <i>이텔리체 italic</i> 
              <b><i>bold-italic</i></b></string>>
</resources>

◉CharSequence 객체로 받아서 처리 할 때.
private void charSequence() {
 CharSequence cs = getText(R.string.styled_text);
 tv.setText(cs);
}

이와 같이 getText() method로 읽어 CharSequence 객체 필드로 보관하면 스타일이 유지된다. 강조나 이탤리체가 적용 안되보이는것은 폰트가 지원을 안하기 때문이다. 지원하는 폰트를 사용하면 적용이 잘된다.

◉String 객체로 받아서 처리 할 때.
private void string() {
 String str = getString(R.string.styled_text);
 tv.setText(str);
}

이와 같이 getString() method로 읽어  String 객체 필드로 보관하면 스타일이 유지되지 않는다. 위에 설명 했다시피 String은 변경금지 문자이기 때문이다.


:

자바 동기화 syncronized

Java 2015. 3. 16. 23:21

동기화의 목적

여러 Thread에서 같은 객체의 값에 접근할 경우 갱신된 값이 누락되는 것을 방지하기 위해 syncronized를 사용한다.

스레드가 한가지 동작을 처리하고 있을 경우 다른 동작이 이루어지지 않도록 차단한다.


너무 많은 동기화는 성능 저하나 프로그램 자체가 멈춰버리는 단점이 있으므로 남발하지 않는다.

우선순위를 가진 스레드에서 동기화된 메소드의 처리가 끝날때까지 기다려야 하므로 성능저하는 당연한듯..

객체, 스레드 2개면 교착상태에 빠질 수 있음.



:

JNI란

Java 2015. 3. 6. 14:58

Java Native Interface

- 자바가 다른 언어와 연동할 수 있도록 도와주는 인터페이스


http://egloos.zum.com/sinuk/v/2676307


Android에서 JNI 세팅

http://dislab.hufs.ac.kr/lab/Android%EC%97%90%EC%84%9C_JNI_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8_%EC%9E%91%EC%84%B1

:

java tool IntelliJ

Java 2015. 2. 24. 14:09
:

자바 메이븐

Java 2015. 1. 13. 10:14
:

디자인패턴; Singleton

Java 2014. 3. 18. 15:06

- 하나의 인스턴스에 접근하는 전역적인 방법.

- 자원의 낭비를 줄이기 위해 인스턴스를 하나만 생성하고 재사용한다.



class Singleton
{
private static Singleton instance;
private Singleton()
{
...
// 생성자가 private 로 되어있어 외부에서 new를 통해 객체 생성이 불가능 하다.
// 매번 객체를 생성하지 않기 때문에 자원을 낭비하지 않는다.
}

public static synchronized Singleton getInstance()
{
if (instance == null)
instance = new Singleton();

return instance;
}
...
public void doSomething()
{
...
}
}


// doSomthing() 메소드에 접근하는 방법은 아래와 같다.

Singleton.getInstance().doSomething();



: