단위테스트(Unit Test)를 작성하는데 AAA 패턴을 이용해서 작성하면 단순하고 균일한 구조를 갖는데 도움을 주며 가독성 또한 좋아진다. 

 

 AAA패턴이란 준비(arrange), 실행(act), 검증(assert) 세 단계로 Test를 작성하는 패턴을 의미한다.

 

- 준비(arrange) : 테스트에 필요한 변수나 객체를 생성한다. 필요에 따라 mock 객체를 만든다.

 

- 실행(act) : 테스트 할 코드를 실행해 본다.

 

- 검증(assert) : 실행한 코드가 설계한대로 정확하게 동작했는지를 검증해본다. Unit Test의 Api인 assertEqals() 등의 코드를 사용하여 검증한다.

 

비슷한 패턴으로 Given-When-Then 패턴이 존재 한다.

 

아래 코드는 AAA패턴을 이용해서 Test 코드를 작성한 것이다.

 

import static org.junit.Assert.*;
import org.junit.Test;

public class MyMathTest {
	@Test
	public void mul_of_two_numbers() {
		// arrange
		MyMath math = new MyMath();
		int first = 5;
		int second = 30;	
		
		// act
		int result = math.mul(first, second);
		
		// assert
		assertEquals(150, result);
	}
}

 

각 단계마다 코드의 길이에 대한 설명이다.

 

 

-  준비(arrange) : 필요한 객체를 생성하고 필요한 변수들을 셋팅하는 과정이기 실행이나 검증 단계보다 코드가 길어질 수 있다. 준비 단계 코드가 너무 길어지고 다른 테스트와의 유사성이 있다면 중복된 부분을 private 함수를 이용해서 리팩토링하는 것도 좋은 방법이다.

 

- 실행(act) : 보통 한줄의 코드이다. 실행 구절이 두줄 이상이라면 잘못 설계된 API일 가능성이 높다.

 

- 검증(assert) : 유닛 테스트란 단일 동작을 검증하는 단위테스트다. 하지만 단일 동작으로 여러 결과를 낼 수 있기 때문에 코드가 길어 질 수 있다.

 

 

 

 

Posted by 꿈만은공돌
,

JAVA 코드를 유닛 테스트 하기위하여 Junit을 이용하여 Eclipse 환경에서의 방법을 알아보자.

이클립스(Eclipse) 버전은 2022-03(4.23.0) 버전을 사용하였다.

JDK는 18.0.1.1 버전을 사용하였다.

최근 몇년간의 버전이라면 아래 방법과 큰차이가 없을 것이다.

외부라이브러리를 번거롭게 수동으로 추가해주지 않아도 된다.

 

이클립스 버전 정보

 

File -> New -> Java Project 를 실행하여 아래와 같은 팝업창에서 프로젝트 명을 입력하고 Finish 버튼을 누른다.

 

신규 자바 프로젝트 생성

 

그 이후에 새로 만들어진 프로젝트에 새로운 Class를 생성한다.

프로젝트에 Src를 클릭하고 오른쪽 버튼을 눌러서 Class를 선택한다. 그러면 아래와 같은 팝업창이 뜨는데 class이름을 입력하고 Finish를 누른다. 

 

Class 생성

 

그리고 아래와 같이 클래스를 작성한다.

 

소스코드 작성

 

그 이후에 프로젝트의 Src에 오른쪽 버튼을 누른 후 New-> Junit Test Case를 선택한다.

 

JUnit Test Case 생성

 

그러면 아래와 같은 팝업창이 뜨는데 New JUnit 4 test를 선택하고 Name을 입력하고 Finish를 누른다.

 

 

 

 

그러면 JUnit 라이브러리가 없으니 추가하라고 나오는데 아래와 같이 선택하고 OK 버튼을 누른다. 

 

JUnit4 라이브러리 추가

 

그러면 아래와 같이 테스트 클래스가 생성된다.

 

 

이 테스트 클래스를 실행하기 위해서는 테스트클래스에 오른쪽 버튼을 눌러 Run As -> JUnit Test 를 클릭한다.

 

 

그러면 아래와 같이 실패했다는 정보를 확인할 수 있다.

 

Junit Test 실패

 

아래와 같이 테스트 클래스의 코드를 변경한다.

 

import static org.junit.Assert.*;
import org.junit.Test;

public class MyMathTest {
	@Test
	public void test() {
		MyMath math = new MyMath();
		assertEquals(10, math.add(3, 7));
	}
}

 

 

그이후에 다시 실행하게 되면 아래이미지와 같이 성공으로 뜬것을 확인할 수 있다.

 

Junit Test 성공

 

Posted by 꿈만은공돌
,

문자열을 자르는 함수에 대해서 정리해보자

프로그래밍 언어마다 문자열을 자르는 함수의 사용방법이 조금씩 다른경우가 많다.

string 의 멤버 함수로 substring()과 split() 두가지가 가장 흔하게 쓰이는 방식이다.

 

첫번째로 substring() 함수는 시작지점과 끝지점을 파라미터로 전달받아서 문자열을 자르게 된다.

substring(시작지점, 끝지점) 이런식으로 사용하면 된다. 

아래이미지를 보도록 하자.

 

 

substring(1, 3) 을 입력하면 인덱스가 1부터 3까지의 글자를 자르게 되는데 B부터 C까지 잘라서 "BC"가 리턴이 된다.

substring(5) 를 입력하면 인덱스 5부터 문자열 끝까지 잘라서 "3de"가 리턴된다.

 

아래 사용 예제를 보도록 하자.

public static void main(String[] args) {		
	String str = "abcdefg12345";
	System.out.println("substring(5) : " + str.substring(5));
	System.out.println("substring(0,1) : " + str.substring(0,1));
	System.out.println("substring(1,2) : " + str.substring(1,2));
	System.out.println("substring(2,3) : " + str.substring(2,3));
	System.out.println("substring(2,10) : " + str.substring(2,10));
}

출력 :

substring(5) : fg12345
substring(0,1) : a
substring(1,2) : b
substring(2,3) : c
substring(2,10) : cdefg123

 

 

만약 문자열 끝에서부터 3글자만 출력하고 싶다면 아래 예제와 같이 사용하면 된다.

public static void main(String[] args) {		
	String str = "abc123def";
	System.out.println(str.substring(str.length()-3, str.length()));
}

출력 :

def

 

그리고 아래예제와 같이 indexOf() 함수를 사용하면 특정 글자 두개를 포함하여 그사이에 글자를 모두 출력하게 된다.

 

public static void main(String[] args) {		
	String str = "abc123def";
    System.out.println(str.substring(str.indexOf("1"), str.indexOf("3") + 1));
}

출력 :

123

 

그런데 substring() 함수를 사용하다가 문자열의 길이보다 긴 값을 substring의 인자로 전달하게 되면 아래 예제와 같이 StringIndexOutOfBoundsException 에러가 발생하게 된다. 총 글자수는 12개이지만 10부터 20을 출력하라고 했기때문에 에러가 발생하였다.

 

public static void main(String[] args) {		
	String str = "abcdefg12345";
	System.out.println("substring(10,20) : " + str.substring(10,20));
}

에러 메시지 :

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: Range [10, 20) out of bounds for length 12
at java.base/jdk.internal.util.Preconditions$1.apply(Preconditions.java:55)
at java.base/jdk.internal.util.Preconditions$1.apply(Preconditions.java:52)
at java.base/jdk.internal.util.Preconditions$4.apply(Preconditions.java:213)
at java.base/jdk.internal.util.Preconditions$4.apply(Preconditions.java:210)
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:98)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckFromToIndex(Preconditions.java:112)
at java.base/jdk.internal.util.Preconditions.checkFromToIndex(Preconditions.java:349)
at java.base/java.lang.String.checkBoundsBeginEnd(String.java:4589)
at java.base/java.lang.String.substring(String.java:2703)
at TestSubString.main(TestSubString.java:5)

 

 

 

이것을 방지하기 위해서는 아래예제와 같이 StringIndexOutOfBoundsException 에러를 예외처리해주면 된다.

 

public static void main(String[] args) {		
	String str = "abcdefg12345";
	try {
		System.out.println("substring(10,20) : " + str.substring(10,20));
	} catch(StringIndexOutOfBoundsException e) {
		System.out.println("Error : "+e.getMessage());
	}		
}

출력 : 

Error : Range [10, 20) out of bounds for length 12

 


 

두번째로 split() 함수는 특정 문자열을 파라미터로 받아서 해당 문자열을 기준으로 문자열을 잘라서 배열에 넣어주는 기능을 한다. String 의 멤버함수이다. 

 

아래이미지를 보면 이해하기 쉬울 것이다.

 

 

위에 이미지를 아래는 코드화 한것이다.

 

public static void main(String[] args) {		
	String str = "ABC,EE,QQ1,5112";
	String arr[] = str.split(",");
	for(String cut : arr) {
		System.out.println(cut);
	}		
}

출력 :

ABC
EE
QQ1
5112

 

 

Posted by 꿈만은공돌
,

 

프로그래밍을 하다보면 특히 게임쪽에서 랜덤(random) 또는 난수 를 생성할 일이 있다.
난수는 무작위 숫자를 뜻하지만 컴퓨터 쪽에선 100% 무작위(랜덤)은 아니다.
정해진 난수표에서 숫자를 가저오는 방식이기 때문이다.


자바(JAVA) 에서 난수를 생성하는 방식은 크게 두가지 이다.


첫번째로 Math.random() 이용하는 방식이다.
Math Class의 random 함수는 double 형 타입으로 0.0 이상 1.0 미만 사이의 값을 반환한다.

 

public class TestRandom {
    public static void main(String[] args) {        
        for(int i =0; i < 10; i++) {
            System.out.print(Math.random()+" ");
        }
        System.out.println("");
    }
}

 

* 결과 값 :

0.1652487713090327 0.286398184817342 0.4336343206580924 0.4295581874855847 0.44636521032290466 0.8715008193305886 0.93917325018134 0.5647002564584279 0.7323427296788428 0.8295767550811228

 

보통은 자연수의 난수가 필요한 경우가 많기 때문에 아래 예제 처럼 0부터 9까지의 난수가 필요하다면 x10을 한 이후에 int형으로 강제 형변환을 시켜주면 된다.

 

public class TestRandom {
    public static void main(String[] args) {        
        for(int i =0; i < 10; i++) {
            System.out.print((int)(Math.random()*10) + " ");
        }
        System.out.println("");
    }
}

 

* 결과 값 :

2 6 3 7 6 9 8 7 9 7 


하지만 이 방식은 직관적이지 않고 형변환등을 하면서 익셉션(Exception) 처리등을 해주어야 하기 때문에 두번째 방식을 추천한다.

 


 

 

 

 

두번째로 Random Class를 이용하는 방식이다.
난수를 생성하는데 필요한 기능 등을 묶어놓은 클레스 이다.
Random Class를 사용하려면 import java.util.Random; 를 해주어야 한다.
Random Class의 맴버변수중에 setSeed를 이용하거나 생성자에 매개변수로 시스템시간을 매개로 전달하면 난수표의 시드값을 초기화 할 수 있다.
아래는 0부터 9까지의 정수를 출력하는 예제이다.

 

import java.util.Random;
 
public class TestRandom {
    public static void main(String[] args) {        
        Random random = new Random(System.nanoTime());
        for(int i =0; i < 10; i++) {
            System.out.print((int)(random.nextInt(10)) + " ");
        }
        System.out.println("");
    }
}


* 결과 값 :


1 3 3 7 6 9 5 7 2 4


아래는 1부터 45까지의 숫자를 출력하는 로또 번호 추첨 예제이다. 랜덤으로 숫자를 추첨하는데 기존에 나왔던 숫자가 있을 경우 다시 재추첨하도록 하였다.

 

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
 
public class TestRandom {
    public static void main(String[] args) {        
        Random random = new Random(System.nanoTime());
        List<Integer> result = new ArrayList<Integer>();
        int num;
        for (int i = 0; i < 6; i++) {
            while (true) {
                num = random.nextInt(45) + 1;
                if (result.contains(num)) {
                    continue;
                } else {
                    result.add(num);
                    System.out.print(num+" ");
                    break;
                }
            }
        }    
        System.out.println("");
    }
}

 

* 결과 값 :

 

12 38 33 29 4 17 

 

 

아래 테이블은 다양한 Random class의 멤버함수 들이다. 이외에도 다양한 함수들이 많이 존재하니 라이브러리를 참고하도록 하자.

함수 설명
nextInt(int i) 0부터 i 까지의 랜덤한 숫자를 리턴
nextInt() Int 타입의 최소 ~ 최대범위 안에서 랜덤한 숫자를 리턴
nextLong() Long 타입의 최소 ~ 최대범위 안에서 랜덤한 숫자를 리턴
nextDouble() Double 타입의 0.0 – 1.0까지의 랜덤한 숫자를 리턴
nextBoolean() boolean타입의 true, false 중 랜덤한 값을 리턴

 

참고 자료 : https://docs.oracle.com/javase/8/docs/api/java/util/Random.html

Posted by 꿈만은공돌
,

JAVA에서 File CLASS는 파일이 존재하는지, 디랙토리가 존재하는지, 사이즈가 몇인지 등을 알 수 있는 편리한 클래스 입니다. 특별한 라이브러리 추가 없이 사용가능하기 때문에 편리합니다.

특히 특정 폴더 밑에 모든 파일들을 삭제하거나 검색하는 등에 기능으로 사용하기 좋습니다.



우선 import java.io.File; 로 import를 시킵니다.


1. exists 함수

파일이 존재하는지 여부를 알 수 있습니다.

반환결과가 boolean으로 파일이 존재하면 참, 없으면 거짓을 반환 합니다.


1
2
3
4
5
6
File f = new File("C://test/a.txt");
if(f.exists()) {
     System.out.println("파일 존재");
else {
      System.out.println("파일 없음");            
}
cs


2. length 함수

file의 사이즈를 측정하는 함수 입니다. 바이트 사이즈 크기를 변수타입 long으로 반환합니다. 


1
2
3
4
5
6
7
    File f = new File("C://test/a.txt");
    if(f.exists()) {
        long len = f.length();
        System.out.println("file Size : " + len);
    } else {
        System.out.println("파일 없음");            
    }
cs



3. isFile 함수

파일인지를 검사하는 함수입니다. 파일이 존재하지 않거나 디렉토리이면 false를 반환, 파일이면 true 반환합니다.


1
2
3
4
5
6
    File f = new File("C://test/");
    if(f.isFile()) {
        System.out.println("파일");  
    } else {
        System.out.println("파일이 아님");            
    }
cs



4. isDirectory 함수

디렉토리인지를 검사하는 함수 입니다. 디랙토리이면 true를 반환하고 파일이거나 존재재하지 않으면 false를 반환합니다.


1
2
3
4
5
6
    File f = new File("C://test/");
    if(f.isDirectory()) {
        System.out.println("디랙토리");  
    } else {
        System.out.println("디랙토리 아님");            
    }
cs



5. isHidden 함수

숨김파일인지를 검사하는 함수 입니다. 파일이나 디랙토리가 숨김으로 되어있으면 true를 반환하고 아니면 false를 반환합니다.


1
2
3
4
5
6
File f = new File("C://test/a.txt");
if(f.isHidden()) {
    System.out.println("숨겨진 파일");  
else {
    System.out.println("숨겨진 파일이 아님");            
}
cs


6. getName 함수

파일에 이름을 반환하는 함수 입니다. 앞에 파일 경로를 제외하고 파일이름만 String 타입으로 반환 합니다.


1
2
3
4
5
File f = new File("C://test/a.txt");
if(f.isFile()) {
    String name = f.getName();
    System.out.println("File Name : " + name);
}
cs


7. getPath 함수

파일의 전체 경로와 이름을 반환하는 함수 입니다.


1
2
3
4
5
File f = new File("C://test/a.txt");
if(f.exists()) {
   String path = f.getPath();
   System.out.println("File Path : " + path);
}
cs



8. listFiles 함수

해당 디랙토리 아래 어떤 파일이나 디렉토리들이 있는지를 반환하는 함수 입니다.

File배열로 반환합니다. 아래 예제를 보면 C://test/ 디렉토리 아래에 있는 모든 파일과 디렉토리를 반환하게 됩니다.


1
2
3
4
5
6
File f = new File("C://test/");
if(f.isDirectory()) {
    File[] fList = f.listFiles();
    for(int i=0; i < fList.length; i++)
        System.out.println(fList[i].getName());
}
cs


9. mkdir 함수

디랙토리 만들기 함수 입니다. 아래 예제대로면 C://test/test2 로 test2 디렉토리를 를 만들게 됩니다.

그러나 C://test 폴더가 존재하지 않으면 실패하게 됩니다. 이럴땐 mkdirs을 사용해야합니다.

결과로 성공여부를 boolean 을 반환합니다.


1
2
3
4
5
6
7
File f = new File("C://test/test2");
boolean result = f.mkdir();
if(result)
   System.out.println("디렉토리 만들기 성공");
else
   System.out.println("디렉토리 만들기 실패");
 
cs




10. mkdirs 함수

위의 9번 mkdir과 거의 같은 기능을 하지만 C://test/test2 에서 상위 폴더들이 없으면 상위폴더들까지 만들게 됩니다.


1
2
3
4
5
6
7
File f = new File("C://test/test2");
boolean result = f.mkdirs();
if(result)
   System.out.println("디렉토리 만들기 성공");
else
   System.out.println("디렉토리 만들기 실패");
 
cs



이외에도 몇가지더 존재하지만 대부분 함수이름을 보면 기능이나 사용방법을 추측해볼 수 있습니다.



Posted by 꿈만은공돌
,


 정규 표현식이라는 표현식을 이용하여 패턴이 매칭하는지 검사 할 수 있다. 예를들어 어떤 문자열이 A부터 C사이에 글자로 시작하면서 5글자이내의 글자인지를 검사하거나 해당 문자열이 숫자로만 이루어지고 10글자 이내의 글자인자를 검사할 수 있다. 정규표현식을 잘 작성하면 해당 문자열이 전화번호형식인지 이메일 형식인지 등을 쉽게 검사할 수 있다. 구글링을 통해 해당 정규표현식은 쉽게 찾을 수 있다.

 정규 표현식을 사용하여 패턴 매칭을 하는 것이 속도도 빠르고 정확하다. 사용자가 코드를 아무리 잘짜더라도 정규표현식을 이용하여 패턴 매칭을 하는 것보다 빠르기는 힘들다.

아래 링크는 정규 표현식을 정리한 위키백과이다. 참고하도록 하자.

https://ko.wikipedia.org/wiki/%EC%A0%95%EA%B7%9C_%ED%91%9C%ED%98%84%EC%8B%9D


 프로그래머들이 많이 사용하고 유용하기 때문에 많은 언어에서는 쉽게 정규표현식을 사용하여 패턴매칭을 할 수 있도록 언어차원에서 라이브러리를 지원해준다.

 JAVA 에서도 정규식을 사용하여 패턴 매칭을 할 수 있다.



간단히 핵심을 정리하자면 아래와 같다. 정말 중요하고 기본적인 내용만을 정리했다. 좀더 자세한 내용은 위에서 소개한 위키를 참고하도록 하면 된다.

. : 하나의 문자를 의미한다.
예제 : A.B 패턴은 AAB(일치), A1B(일치), AAB(불일치), AB(불일치) 이다.

? : 아무문자도 없거나 하나의 문자 있는 것을 의미한다.

예제 : A?B 패턴은 AAB(일치), AB(일치), AAA(불일치), AAAB(불일치) 이다.


* : 0개나 하나이상의 문자가 있는 것을 의미한다.

예제 : A*B 패턴은 AB(일치), AAAAAAAAAAAB(일치), A123B(일치), AAAAAAAAAAAA(불일치) 이다.


+ : +앞에있는 문자가 한번이상 반복됨을 의미한다.

예제 : AB+ 패턴은 AB(일치), ABBBB(일치), A(불일치), ABC(불일치) 이다.


[] : [ ] 사이에 있는 형식이 일치하는것을 의미한다. 즉 [AB] 는 A, B만일치, [A-Z] 는 A부터 Z중 하나의 문자와 일치한다.

예제 : [A-C] 패턴은 A(일치), B(일치), AB(불일치), BC(불일치) 이다.


() : ( ) 사이에 문자가 하나의 묶음이된다. 즉 (ab)+ 는 abababab 와 일치한다.

예제 : (ab) 패턴은 ab(일치), ba(불일치) 이다.


{} : { } 사이에 숫자를 쓰면 그 숫자만큼 패턴이 반복됨을 의미한다.

[A-C]{1,3}는 A,B,C 를 1개에서 3개 조합하면 된다. AAA도 가능하고 A, BA, ABC, CBA도 가능하다.

예제 : [A-C]{1,3} 패턴은 AA(일치), CBC(일치), ADA(불일치), ACCC(불일치) 이다.


[^] : ^다음에 문자를 쓰면  해당 문자를 제외한다는 의미한다.

예제 : [^A-C]D 패턴은 DD(일치), AD(불일치), D(불일치), DDD(불일치) 이다.


JAVA에서 정규표현실을 사용하여 패턴매칭을 하는 예시는 아래와 같다.

2가지의 import도 반드시 시켜줘야 한다. Pattern 클래스는 패턴을 저장하고 Matcher라는 클래스는 검사결과를 저장한다. 그래서 Matcher에 함수인 matches 함수를 사용하여 결과를 boolean 으로 리턴받을 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class RegexTestStrings {
    public static void main(String[] args) {        
         Pattern pattern = Pattern.compile("패턴 입력");  
         Matcher match = pattern.matcher("검사할 문자열"); 
         boolean bool = match.matches();
         if(bool)
             System.out.println("일치");
         else
             System.out.println("불일치");
     }
}
cs


아래는 실제 사용 예제이다.

A부터C사이의 글자로 시작을하고 그다음 글자가 D인 패턴과 일치하는지 검사한다.

AD는 해당 패턴과 일치한다. 따라서 일치가 출력된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class RegexTestStrings {
    public static void main(String[] args) {        
        Pattern pattern = Pattern.compile("[^A-C]D"); 
        Matcher match = pattern.matcher("AD"); 
        boolean bool = match.matches();
        if(bool)
            System.out.println("일치");
        else
            System.out.println("불일치");
    }
}
cs


아래링크는 C#에서의 정규식을 사용한 패턴매칭에 관한 포스팅이다. 참고하도록 하자.

C#에서 정규식을 사용하여 패턴 매칭(Regex, IsMatch) : http://hijuworld.tistory.com/22


Posted by 꿈만은공돌
,

프로그래밍을 하다보면 딜레이가 발생하거나해서 어느 부분이 느린지 알아내야 하는 경우가 생길 수 있습니다.


또는 알고리즘을 공부하다보면 내가 구현한 알고리즘의 속도를 알고싶을 때가 있습니다.


그럴때 특정 구간에 코드 실행시간을 알아야내야 하는 경우에 필요한 포스팅 입니다.


JAVA에서 코드에 실행 시간을 측정하거나 특정 구간에 시간이 얼마나 소요되는지를 알고 싶을때 사용하는 코드 입니다.


현재 시간을 받아오는 System 함수인 System.currentTimeMillis() 함수를 이용하면 쉽게 구할 수 있습니다.

시작 구간과 끝나는 구간에 각각 해당 함수를 써서 시간을 받아오고 두 시간간의 차이를 계산하면 ms 단위의 시간차를 구할 수 있습니다.


ms를 초(s)로 변환하고 싶다면 /1000을 해주면 됩니다.

추가로 초(s)를 분(m) 구하고 싶다면 /60을 추가로 해주면 됩니다.




- 사용 방법 -

1
2
3
4
5
6
7
long beforeTime = System.currentTimeMillis(); //코드 실행 전에 시간 받아오기
        
//실험할 코드 추가
        
long afterTime = System.currentTimeMillis(); // 코드 실행 후에 시간 받아오기
long secDiffTime = (afterTime - beforeTime)/1000//두 시간에 차 계산
System.out.println("시간차이(m) : "+secDiffTime);



- 사용 예시 -

1
2
3
4
5
6
7
8
9
10
11
12
13
long beforeTime = System.currentTimeMillis();
        
int sum = 0;
for (int i = 0; i < 1000000; i++) {
    for (int j = 0; j < 50000; j++) {
        sum += i*j;
    }
}
System.out.println(sum);
    
long afterTime = System.currentTimeMillis(); 
long secDiffTime = (afterTime - beforeTime)/1000;
System.out.println("시간차이(m) : "+secDiffTime);




- 출력 결과 -

1636142336 

시간차이(m) : 19

Posted by 꿈만은공돌
,