1 1. 자바 9의특징 2. 자바 10의특징 3. 이클립스플러그인설치와 Amateras Modeler 사용 4. 외부라이브러리추가와 logback 사용
2 Java 프로그래밍 1. 자바 9 의특징 1.1 프로젝트직소 (Jigsaw) 의모듈시스템 (1) 모듈시스템 [ 그림 17.1] 의존성지옥
3 (2) System library의모듈화 [ 그림 17.2] 자바 8 과자바 9 의 System Library 구성비교
4 Java 프로그래밍 [ 그림 17.3] 모듈화된 JDK ( 자료출처 : https://www.javacodegeeks.com) (3) 모듈 모듈이름은모듈을나타내는유일한값으로일반적인패키지작명법에근거해서작성한다. export는현재의모듈을다른외부모듈에서사용할수있도록공개하는패키지를의미한다. 클래스가 public이라고할지라도 export에등록되지않으면외부에서는이클래스에접근할수없다. requires는현재의모듈과의존관계가있는다른모듈의이름들이다. (4) 간단한모듈테스트
5 [com.acme.calculator.api.close.minusmodule.java] 1 package com.acme.calculator.api.close; 2 3 public class MinusModule { 4 public double minus(double num1, double num2) { 5 return num1 - num2; 6 } 7 } [com.acme.calculator.api.open.plusmodule.java] 1 package com.acme.calculator.api.open; 2 3 public class PlusModule { 4 public double add(double num1, double num2) { 5 return num1 + num2; 6 } 7 } [com.acme.calculator.internal.addmoduleinternalclient.java] 1 package com.acme.calculator.internal; 2 // 내부에서의접근은문제없음 3 import com.acme.calculator.api.open.plusmudule; 4 import com.acme.calculator.api.close.minusmodule; 5 6 public class AddModuleInternalClient { 7 public static void main(string[] args) { 8 PlusMudule pmodule = new PlusMudule(); 9 System.out.println(pModule.add(100, 100)); 10 11 MinusModule mmosule = new MinusModule(); 12 System.out.println(mMosule.minus(100, 100)); 13 } 14 }
6 Java 프로그래밍 [module-info.java] 1 module com.acme.calculator { 2 exports com.acme.calculator.api.open; 3 } 1 행모듈의이름이 com.acme.calculator 인모듈을선언한다. 2 행 com.acme.calculator.api.open 패키지를 exports 에등록한다. 따라서 PlusModule 은외부로노출된다. [module-info.java] 1 module com.acme.jigsawuser { 2 exports com.acme.jigsawuser; 3 requires com.acme.calculator; 4 } 1행 모듈의이름이 com.acme.jigsawuser인모듈을생성한다. 2행 com.acme.jigsawuser 패키지를 exports 해서외부에서사용할수있게한다. 3행 requires에 com.acme.calculator 모듈을등록한다. 이모듈은앞서생성한 jigsaw_module의모듈이름이다.
7 [com.acme.jigsawuser. JigSawClient.java] 1 package com.acme.jigsawuser; 2 3 //import com.acme.calculator.api.close.minusmodule; 4 import com.acme.calculator.api.open.plusmodule; 5 6 public class JigSawClient { 7 public static void main(string[] args) { 8 PlusModule pmodule = new PlusModule(); 9 System.out.println(pModule.add(100, 100)); 10 11 //MinusModule mmodule = new MinusModule(); 12 } 13 } 8-9행모듈참조를통해 jigsaw_module에있는 PlusModule을참조하고사용하는데아무런문제가없다. 11행 MinusModule는 jigsaw_module의 public 클래스임에도불구하고 exports 항목에등록되어있지않기때문에외부에서참조할수없다.
8 Java 프로그래밍 1.2 새로추가된개발도구 (1) jshell 등장 (2) HTML5 기반의 Javadoc 생성 html4: HTML 4.01 형식의 Javadoc 생성 html5: HTML 5 형식의 Javadoc 생성 javadoc -html5 -encoding utf-8 -sourcepath./src -subpackages ch02 -d./doc 1.3 프로그래밍방식변경 (1) try ~ with ~ resource 문의개선
9 void trywithresourcesbyjava7() throws IOException { //try() 외부에서생성된객체 BufferedReader reader1 = new BufferedReader(new FileReader("test.txt")); // try() 에별도의객체선언후할당해야자동 close 처리 try (BufferedReader reader2 = reader1) { // do something } } void trywithresourcesbyjava9() throws IOException { BufferedReader reader = new BufferedReader(new FileReader("test.txt")); try (reader) { // do something } } (2) 인터페이스에 private 메서드추가가능 [etc.privatemethod.privatemethodtest.java] 1 package etc.privatemethod; 2 3 interface SomeInterface { 4 static void methoda() { 5 internalcommonmethod(); 6 } 7 8 static void methodb() { 9 internalcommonmethod(); 10 } 11 12 private static void internalcommonmethod() { 13 // 공통처리 14 } 15 }
10 Java 프로그래밍 16 17 public class PrivateMethodTest { 18 19 public static void main(string[] args) { 20 SomeInterface.methodA(); 21 SomeInterface.methodB(); 22 } 23 } (3) Diamond Operator 의개선 List<String> strs = new ArrayList<>(); Comparable<String> comp = new Comparable<String>() { @Override public int compareto(string o) { return 0; } }; Comparable<String> comp = new Comparable<>() { @Override public int compareto(string o) { return 0; } }; 1.4 새로추가된코어라이브러리 (1) 불변의 List, Set, Map, Map.Entry를만들기위한팩토리메서드제공
11 List<Character> list = new ArrayList<Character>(); list.add('x'); // 리스트를수정불가하게만듬 List<Character> immutablelist = Collections.unmodifiableList(list); immutablelist.add('z');// java.lang.unsupportedoperationexception [etc.immutablecollection.immutablecollectiontest.java] 1 package etc.immutablecollection; 2 3 import java.util.list; 4 import java.util.map; 5 6 public class ImmutableCollectionTest { 7 8 public static void main(string[] args) { 9 List<Object> emptyimmutablelist = List.of(); 10 // UnsupportedOperationException 11 // emptyimmutablelist.add("hello"); 12 System.out.println(emptyImmutableList); 13 14 List<String> notemptyimmutablelist = List.of("Hello Immutable List"); 15 System.out.println(notEmptyImmutableList); 16 17 Map<Object, Object> emptyimmutablemap = Map.of(); 18 System.out.println(emptyImmutableMap); 19 Map<Integer, String> notemptyimmutablemap = 20 Map.of(1, "one", 2, "two", 3, "three"); 21 System.out.println(notEmptyImmutableMap); 22 } 23 } 실행결과 [] [Hello Immutable List] {} {2=two, 3=three, 1=one}
12 Java 프로그래밍 (2) Process 관련 API의개선 [etc.processapi.processapitest.java] 1 package etc.processapi; 2 3 import java.util.optional; 4 5 public class ProcessAPITest { 6 public static void main(string[] args) { 7 ProcessHandle currentprocess = ProcessHandle.current(); 8 System.out.println("Current Process Id: = " + currentprocess.pid()); 9 Optional<String> user = currentprocess.info().user(); 10 user.ifpresent(system.out::println); 11 } 12 } (3) CompletableFuture API의개선 [API] public static Executor delayedexecutor(long delay, TimeUnit unit) [ 활용예 ] Executor exe = CompletableFuture.delayedExecutor(50L, TimeUnit.SECONDS);
13 [API] public CompletableFuture<T> ortimeout(long timeout, TimeUnit unit) [ 활용예 ] int TIMEOUT = 3; CompletableFuture<String> future = fiveminutework("5 분정도걸립니다.").orTimeout(TIMEOUT, TimeUnit.SECONDS).whenComplete((result, error) -> { if (error == null) { System.out.println("The result is: " + result); } else { System.out.println(TIMEOUT + " 이지났습니다."); } }); [API] public CompletableFuture<T> completeontimeout(t value, long timeout, TimeUnit unit) [ 활용예 ] int TIMEOUT = 3; CompletableFuture<String> future = fiveminutework("5 분정도걸립니다.").completeOnTimeout("JavaTechnology", TIMEOUT, TimeUnit.SECONDS).whenComplete((result, error) -> { if (error == null) { System.out.println("The result is: " + result); } else { // 이문장은절대호출되지않음 System.out.println(TIMEOUT + " 이지났습니다."); } }); (4) ReactiveStream API 추가 java.util.concurrent.flow java.util.concurrent.flow.publisher
14 Java 프로그래밍 java.util.concurrent.flow.subscriber java.util.concurrent.flow.processor (5) Optional 클래스강화 [API] public Stream<T> stream() [ 활용예 ] List<Object> list = Stream.of(Optional.empty(), Optional.of("one"), Optional.of("two"), Optional.of("three")).flatMap(Optional::stream).collect(Collectors.toList()); System.out.println(list); [API] public void ifpresentorelse(consumer<? super T> action, Runnable emptyaction) [ 활용예 ] Optional<Integer> max = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).max(Integer::compare); max.ifpresentorelse(x -> System.out.println(" 최대값 : " + x), () -> System.out.println(" 원하는값이없습니다.") ); (6) 스트림 API 추가
15 [API] public static IntStream iterate(int seed, IntPredicate hasnext, IntUnaryOperator next) [ 활용예 ] IntStream.iterate(1, i -> i < 20, i -> i * 2).forEach(System.out::println); //1, 2, 4, 8, 16 [API] default Stream<T> takewhile(predicate<? super T> predicate) [ 활용예 ] // 순차스트림의경우 Stream.of(1, 2, 3, 4, 5, 6).takeWhile(i -> i <= 3).forEach(System.out::println); // 1, 2, 3 // 비순차스트림의경우 Stream.of(1, 6, 5, 2, 3, 4).takeWhile(i -> i <= 3).forEach(System.out::println); // 1 [API] default Stream<T> dropwhile(predicate<? super T> predicate) [ 활용예 ] // 순차스트림의경우 Stream.of(1, 2, 3, 4, 5, 6).dropWhile(i -> i <= 3).forEach(System.out::println); // 4, 5, 6 // 비순차스트림의경우 Stream.of(1, 6, 5, 2, 3, 4).dropWhile(i -> i <= 3).forEach(System.out::println); // 6, 5, 2, 3, 4
16 Java 프로그래밍 [API] public static<t> Stream<T> ofnullable(t t) [ 활용예 ] Map<Integer, String> mapnumber = new HashMap<>(); mapnumber.put(1, "One"); mapnumber.put(2, "Two"); mapnumber.put(null, null); List<String> newstringnumbers = Stream.of(null, 1, 2, 3).flatMap(s -> Stream.ofNullable(mapNumber.get(s))).collect(Collectors.toList()); System.out.println(newstringNumbers); // [One, Two] 2. Java 10 의특징 [ 그림 17.4] JDK release 계획 ( 출처 : https://twitter.com/java)
17 2.1 로컬변수에대한타입추정가능 List<String> strlist = new ArrayList<>(); public class UseVar { public static void main(string[] args) { var num = 10; System.out.println(num); // 10 var str = "Hello"; System.out.println(str.getClass().getName()); // java.lang.string } } var list = new ArrayList<String>(); System.out.println(list.getClass().getName()); // java.util.arraylist 2.2 가비지컬렉션관련개선사항 (1) G.C 인터페이스적용
18 Java 프로그래밍 (2) G1 G.C의병렬처리지원 2.3 기타 (1) 대안의메모리장치에힙메모리할당가능 (2) 개발을효율화하기위해 JDK Forest( 포레스트 ) 저장소를하나의저장소로통합 / 강화 (3) JDK에서루트인증서제공 (4) Java 기반의 JIT 컴파일러
19 3. 이클립스플러그인 (Plugin) 설치와 Amateras Modeler 사용 직접설치하는경우 : 플러그인배포사이트에직접접속해서플러그인파일을다운로드한뒤에사용자가이클립스에설치할수있다. 플러그인의 update site 정보를사용하는경우 : 각플러그인의 location 정보를 URL 형태로작성하고네트워크를통해서플러그인파일을다운로드하여설치할수있다. Eclipse Market Place에등록된경우 : 가장마지막에추가된방식으로추가될플러그인에대한상세정보와다른개발자들의선호도까지확인할수있다. 3.1 Amateras Modeler 설치 [ 그림 17.5] Available Software 확인화면
20 Java 프로그래밍 [ 그림 17.6] update site 등록화면 [ 그림 17.7] update site 정보가등록된후 Available Software 화면 [ 그림 17.8] 보안에대한경고및확인화면
21 [ 그림 17.9] 플러그인설치확인 [ 그림 17.10] 파일위치지정및파일명지정
22 Java 프로그래밍 [ 그림 17.11] 클래스다이어그램작성도구모음 select : 편집창에서개별개체를선택하는기능제공 Marque : 편집창에서다수의개체를선택하는기능제공 Note : 상세설명을붙이는 note를작성하기위한기능제공 Anchor to Note : Note와개체간의연결링크를만드는기능제공 Class : Class를정의하는기능제공 Enum : Enum을정의하는기능제공 Interface : Interface를정의하는기능제공 Dependency : 의존관계를설정하는기능제공 Association : 연관관계를설정하는기능제공 Generalization : 클래스간상속관계를설정하는기능제공 Realization : 인터페이스에대한구현임을설정하는기능제공 Aggregation : 집합연관관계를설정하는기능제공 Composition : 복합연관관계를설정하는기능제공
23 3.2 Amateras Modeler 를이용해 Class Diagram 작성 [ 그림 17.12] Class 개체에멤버변수추가 [ 그림 17.9] 이클립스의가시성표현
24 Java 프로그래밍 [ 그림 17.13] 메서드의파라미터설정화면 [ 그림 17.14] Class 개체에메서드추가 [ 그림 17.15] Class 개체에생성자추가
25 [ 그림 17.16] Generalization 을이용한상속관계의표현 [ 그림 17.17] Realization 을이용한구현관계표현 [ 그림 17.18] Aggregation 을이용한연관관계표현
26 Java 프로그래밍 (1) 클래스다이어그램을통한코드생성 [ 그림 17.19] Java Source 코드로의 export 메뉴 [ 그림 17.20] Java Code 생성화면 [Person.java] 1 public class Person { 2 private String name; 3 public int id; 4 5 public void setname(string name) { 6 } 7 8 public String printinfo() { 9 return null; 10 } 11 12 public Person(String name, int id) { 13 } 14 }
27 (2) 역공학 (Reverse Engineering) 으로기존의클래스를이용한클래스다이어그램생성 [ 그림 17.21] 클래스를기반으로생성된클래스다이어그램 4. 외부라이브러리추가와 logback 사용
28 Java 프로그래밍 4.1 logback 소개및설치 click 1 click 2 [ 그림 17.22] logback 다운로드페이지 logback-classic-1.2.3.jar logback-core-1.2.3.jar slf4j-api-1.7.25.jar [ 그림 17.23] logback 패키지구성 (1) 이클립스에라이브러리등록
29 [ 그림 17.24] User Library 등록 1 [ 그림 17.25] User Library 등록 2 [ 그림 17.26] User Library 등록 3
30 Java 프로그래밍 [ 그림 17.27] User Library 등록 4 [ 그림 17.28] User Library 등록 5 [ 그림 17.29] User Library 사용 1
31 [ 그림 17.30] User Library 사용 2 [ 그림 17.31] User Library 사용 3 4.2 logback 사용 [ 표 17.1] LoggerFactory 의주요메서드 메서드명 getlogger() 선언부와설명 public static Logger getlogger(class<?> clazz) clazz 에서사용될 Logger 객체를리턴한다. public static Logger getlogger(string name) name 클래스에서사용할 Logger 객체를리턴한다.
32 Java 프로그래밍 [ 표 17.2] Logger 의주요메서드 메서드명 선언부와설명 trace() debug() info() warn() error() public void trace(string format, Object... arguments) TRACE 레벨의로그를남긴다. format 에는출력될로그의형식을지정할수있 으며 {} 를이용해 argument 를받을수있다. format 에표시된 {} 의개수는 arguments 의개수와동일해야한다. public void debug(string format, Object... arguments) DEBUG 레벨의로그를남긴다. format 과 arguments 내용은 trace 와동일하다. public void info(string format, Object... arguments) INFO 레벨의로그를남긴다. format 과 arguments 내용은 trace 와동일하다. public void warn(string format, Object... arguments) WARN 레벨의로그를남긴다. format 과 arguments 내용은 trace 와동일하다. public void error(string format, Object... arguments) ERROR 레벨의로그를남긴다. format 과 arguments 내용은 trace 와동일하다. public void error(string msg, Throwable t) ERROR 레벨의로그를남긴다이때 msg 와 t 에대한 printstacktrace() 가동작 한다. [etc.logback.logbacktest.java] 1 package etc.logback; 2 3 import org.slf4j.logger; 4 import org.slf4j.loggerfactory; 5 6 public class LogbackTest { 7 private static final Logger logger = 8 LoggerFactory.getLogger(LogbackTest.class); 9 public static void main(string[] args) { 10 logger.trace("trace msg{}, {}", "trace1", "trace2"); 11 logger.debug("debug msg{}, {}", "param1", "debug2"); 12 logger.info("info msg{}, {}", "info1", "info2"); 13 logger.warn("warn msg{}, {}", "warn1", "warn2"); 14 logger.error("error msg{}, {}", "error1", "error2"); 15 } 16 } 실행결과 22:09:02.037 [main] DEBUG etc.logback.logbacktest - debug msgparam1, debug2 22:09:02.041 [main] INFO etc.logback.logbacktest - info msginfo1, info2 22:09:02.041 [main] WARN etc.logback.logbacktest - warn msgwarn1, warn2 22:09:02.041 [main] ERROR etc.logback.logbacktest - error msgerror1, error2
33 7 행로깅을위해 LoggerFactory 를통해 Logger 를획득한다. 10-14 행 trace 에서 error 까지로그를출력한다. 4.3 logback 설정 <?xml version="1.0" encoding="utf-8"?> <configuration> <property/> <appender>...</appender> <root>...</root> <logger>...</logger> </configuration> (1) <property> \ <property name="dev_home" value="c:/temp" /> (2) <appender>
34 Java 프로그래밍 <appender name="stdout" class="ch.qos.logback.core.consoleappender"> <encoder> <pattern>[%d{yy-mm-dd HH:mm:ss}] [%5p] [%thread] [%c{1}.%m-%3l] %m %n</pattern> </encoder> </appender> %d{yy-mm-dd HH:mm:ss} : 로그를출력하는시간표시형식 %5p : 로그의레벨을총 5글자로나타냄 %thread : 현재스레드이름 %c{1} : 패키지를포함한클래스이름을표시함단패키지이름은 1글자씩만표시 %M : 메서드이름 %3L : 행번호를최소한 3자리로표시 %m : 메시지 %n : 줄바꿈표시 <property name="dev_home" value="c:/temp" /> <appender name="dailyfile" class="ch.qos.logback.core.rolling.rollingfileappender"> <file>${dev_home}/logfile.log</file> <rollingpolicy class="ch.qos.logback.core.rolling.timebasedrollingpolicy"> <filenamepattern>/log/logfile.%d{yyyy-mm-dd}.log</filenamepattern> <maxhistory>30</maxhistory> </rollingpolicy> <encoder> <pattern>[%d{yy-mm-dd HH:mm:ss}] [%5p] [%thread] [%c{1}.%m-%3l] %m %n</pattern> </encoder> </appender>
35 (3) <root> <root level="trace"> <appender-ref ref="stdout" /> <appender-ref ref="dailyfile" /> </root> (4) <logger> <logger name="org.springframework" level="trace"> <appender-ref ref="dailyfile" /> <appender-ref ref="stdout" /> </logger> [logback.xml] 1 <?xml version="1.0" encoding="utf-8"?> 2 <configuration> 3 <!-- 콘솔로그 --> 4 <appender name="stdout" 5 class="ch.qos.logback.core.consoleappender"> 6 <encoder> 7 <pattern> 8 [%d{yy-mm-dd HH:mm:ss}] [%5p] [%thread] 9 [%c{1}.%m-%3l] %m %n 10 </pattern> 11 </encoder> 12 </appender>
36 Java 프로그래밍 13 14 <!-- 날짜별로그 --> 15 <property name="dev_home" value="c:/temp" /> 16 <appender name="dailyfile" 17 class="ch.qos.logback.core.rolling.rollingfileappender"> 18 <file>${dev_home}/logfile.log</file> 19 <rollingpolicy 20 class="ch.qos.logback.core.rolling.timebasedrollingpolicy"> 21 <filenamepattern> 22 /log/logfile.%d{yyyy-mm-dd}.log</filenamepattern> 23 <maxhistory>30</maxhistory> 24 </rollingpolicy> 25 <encoder> 26 <pattern> 27 [%d{yy-mm-dd HH:mm:ss}] [%5p] [%thread] 28 [%c{1}.%m-%3l] %m %n 29 </pattern> 30 </encoder> 31 </appender> 32 33 <!-- root 로거기본설정 --> 34 <root level="trace"> 35 <appender-ref ref="stdout" /> 36 <appender-ref ref="dailyfile" /> 37 </root> 38 39 <!-- 특정로거설정 --> 40 <logger name="org.springframework" level="trace"> 41 <appender-ref ref="dailyfile" /> 42 <appender-ref ref="stdout" /> 43 </logger> 44 </configuration> 4.4 logback.xml 적용확인 실행결과 [18-01-24 23:17:42] [TRACE] [main] [e.l.logbacktest.main- 10] trace msg - trace1, trace2 [18-01-24 23:17:42] [DEBUG] [main] [e.l.logbacktest.main- 11] debug msg - param1, debug2 [18-01-24 23:17:42] [ INFO] [main] [e.l.logbacktest.main- 12] info msg - info1, info2 [18-01-24 23:17:42] [ WARN] [main] [e.l.logbacktest.main- 13] warn msg - warn1, warn2 [18-01-24 23:17:42] [ERROR] [main] [e.l.logbacktest.main- 14] error msg - error1, error2 \
37 <root level="info"> <appender-ref ref="stdout" /> <appender-ref ref="dailyfile" /> </root> 실행결과 [18-01-24 23:25:10] [ INFO] [main] [e.l.logbacktest.main- 12] info msg - info1, info2 [18-01-24 23:25:10] [ WARN] [main] [e.l.logbacktest.main- 13] warn msg - warn1, warn2 [18-01-24 23:25:10] [ERROR] [main] [e.l.logbacktest.main- 14] error msg - error1, error2