물리 계층의 역할과 랜 카드의 구조

 

전기 신호

0과 1로 이루어진 이진 데이터를 전기 신호로 변환하기 위하여서 사용되는 계층은 물리 계층이다.

 

아날로그 신호

물결 모양을 그리는 신호를 말하며 전화 회선이나 라디오 방송에 사용되는 신호이다.

 

랜 카드

송신하여야할 데이터를 전기 신호로 변환하며, 전기 데이터를 이진 데이터로 변환하는 장치이다.

 

케이블의 종류와 구조

 

전송 매체

네트워크 구조에서 전기로 변환된 데이터가 흐르는 물리적인 선로를 말한다.

 

트위스트 페어 케이블 ( LAN Cable )

선로 내부에 가닥들을 꼬아놓은 것을 말한다.

 

UTP 케이블

구리 선 여덟 개를 두 개씩 꼬아 만든 네 쌍의 전선으로 실드로 보호되어 있지 않은 케이블이다.

 

실드

금속 호일이나 금속의 매듭과 같은 것으로 외부에서 발생하는 노이즈를 막는 역할을 한다.

 

노이즈

케이블에 전기 신호가 흐를 때 발생하는 현상으로 데이터 흐름에 영향을 준다.

 

STP 케이블

구리 선 두개를 꼬아 만들어낸 전선을 실드로 보호하는 케이블이다.

 

다이렉트 케이블

구리 선 여덟 개를 같은 순서로 커넥터에 연결한 케이블이다.

 

크로스 케이블

구리 선 여덟 개 중 한쪽 커넥터의 1번과 2번에 연결되는 구리 선을 3번과 6번에 연결한 케이블이다.

 

리피터, 허브의 구조

 

리피터

일그러진 전기 신호된 신호를 복원 (정형)하고, 들어오는 신호를 증폭하는 네트워크 중계 장비이다.

 

허브

실제로 통신하는 통로 (포트)를 여러 개 가지고 있는 네트워크 장비를 말한다.

리피터와 마찬가지로 전기 신호를 정형하고 증폭하는 기능을 한다.

 

여러 개의 포트를 가짐으로 컴퓨터 여러 대와 통신할 수 있다.

  • 하지만 특정 포트로 데이터를 받게 되면 모든 포트에게 같은 데이터를 전송한다.

 

데이터 링크 계층의 역할과 이더넷

 

데이터 링크 계층

네트워크 장비 간에 신호를 주고받는 규칙(일반적으로 이더넷)을 정하는 계층이다.

네트워크 기기 간에 데이터를 전송하고 물리 주소를 결정한다.

 

이더넷

사무실이나 가정에서 일반적으로 사용되는 랜과 관련하여 가장 많이 활용되는 기술 규격이다.

허브나 스위치 등과 연결된 컴퓨터들이 데이터를 통신할 때 사용한다.

 

충돌

데이터를 한 번에 하나만 전송할 수 있는 채널에서 두 개 이상의 전송 장치가 동시에 패킷을 보냈을 경우 발생하는 현상이다.

 

충돌 도메인

충돌이 발생하였을 경우 그 영향이 미치는 범위를 말한다.

허브에서 충돌이 발생한다면, 그 허브를 통해 연결된 모든 단말기가 충돌 도메인이 된다.

 

CSMA/CD (Carrier Sense Multiple Access with Collision Detection)

이더넷에서 사용하는 기술의 약어를 말하며, 충돌을 방지하기 위해 데이터를 보내는 시점을 늦추는 것을 말한다.

  • CS : 데이터를 보내려고 하는 컴퓨터가 케이블에 신호가 흐르고 있는지 확인하여야 하는 규칙
  • MA : 케이블에 데이터가 흐르고 있지 않다면 데이터를 보낼 수 있는 규칙
  • CD : 충돌이 발생하고 있는지를 확인한다는 규칙

 

MAC 주소의 구조

 

MAC 주소

랜 카드가 제조될 당시에 새겨지는 주소로 물리 주소라고도 부른다.

각각의 기기가 유일한 번호로 할당되어 있기에 특정한 하나의 기기만을 식별할 수 있다.

 

MAC 주소는 48 Bit 로 이루어져 있다.

  • 전면부 24 Bit : 랜 카드를 만든 제조사의 번호
  • 후면부 24 Bit : 제조사가 랜 카드에 붙인 일련번호

TCP/IP 모델의 네트워크 계층 (OSI의 데이터 링크 계층)에서는 이더넷 헤더와 트레일러를 붙이게 되는데 이때 이더넷 헤더는 MAC 주소(6byte), 출발지 MAC 주소(6byte), 유형(2byte)으로 이루어진다.

 

유형? (16진수 데이터)

이더넷으로 전송되는 상위 계층의 프로토콜 종류를 나타낸다.

  • 0800 : IPv4
  • 0806 : ARP
  • 8035 : RARP
  • 814C : SNMP over Ethernet
  • 86DD : IPv6

FCS ( Frame Check Sequence, 트레일러)

데이터 전송 도중에 오류가 발생하는지 확인하는 용도로 사용된다.

이더넷 헤더와 트레일러가 추가된 상태의 데이터를 프레임이라고 부른다.

 

스위치의 구조

 

스위치 (L2 Switch, Switching Hub)

네트워크 계층(데이터 링크)에서 동작하는 네트워크 장비를 말한다.

랜을 구성할 때 사용하는 단말기 간 스위칭 기능이 있는 장비로써, 단말기에서 특정한 다른 단말기로 패킷을 보내는 기능을 제공함으로써 통신 효율을 향상시킨다.

 

MAC 주소 테이블 (MAC address table)

스위치의 포트 번호와 해당 포트에 연결되어 있는 컴퓨터의 MAC 주소가 등록되는 데이터베이스.

 

단말기가 프레임을 전송하면 MAC 주소 테이블을 확인한 후 없는 경우 등록하는 절차를 가진다.

→ 이를 MAC 주소 학습 기능이라고 부른다.

 

플러딩(flooding)

보내야 할 단말기의 주소 정보가 등록되지 않은 경우에는 연결된 포트로 데이터를 전송하는 것을 말한다.

 

MAC 주소 필터링

보내야할 단말기의 주소 정보가 등록된 경우 해당 단말기에게만 프레임을 전송하게 되는 것을 말한다.

 

ARP

네트워크 계층에서 IP 주소를 MAC 주소로 변환하기 위하여 사용되는 프로토콜이다.

 

ARP 요청

이더넷 프레임을 전송하려면 목적지의 MAC 주소가 필요하게 되는데, 해당 주소를 알지 못할 경우, 네트워크에 IP 정보를 가지고 브로드 캐스트를 진행하게 됨을 말한다.

 

ARP 응답

ARP 요청 이후 해당 IP 정보를 가지지 않은 단말기들은 모두 요청을 무시하며, 해당 IP 정보를 가진 단말기만이 MAC

주소를 응답으로 보내게 된다. 데이터를 보내는 단말기는 ARP 응답으로 받은 MAC 주소를 이더넷 헤더에 추가함으로써 프레임을 만들고 전송할 수 있게 된다.

 

ARP 테이블

추가적으로 받은 MAC 주소를 IP 주소와 매핑하여, 메모리에 보관하게 되는데 이를 ARP 테이블이라 한다. 이후에는 해당 테이블 정보를 이용하여 프레임을 만들고 전송한다.

 

만약 다른 단말기의 IP 주소가 변경될 경우 MAC 주소도 함께 변경됨으로 데이터를 영구적으로 보관하지 않고, 보관 기간을 ARP 캐시를 이용하여 관리한다. (기간 만료 시에는 ARP 요청을 보낸다)

 

데이터가 케이블에서 충돌하지 않는 구조

 

전이중 통신

데이터의 송수신이 동시에 발생하는 통신 방식을 말한다.

서로 다른 회선이나 주파수를 이용하여 데이터 신호가 충돌되는 상황을 방지한다.

L2 Switch로 통신 중계, 단말기 간의 크로스 케이블을 이용 등 이런 경우 전이중 통신이 가능하다.

 

반이중 통신

데이터의 송수신이 번갈아가면서 통신하는 방식을 말한다.

허브를 통해 연결한 경우 반이중 통신이라고 말하며, 충돌이 발생할 위험이 있다.

 

이더넷의 종류와 특징 - 스킵.

'Book! > 모두의 네트워크' 카테고리의 다른 글

2장 네트워크의 기본 규칙  (0) 2020.12.22
1장 네트워크 첫걸음  (0) 2020.12.21

 

4주 차 시작합니다!

 

선택문 (switch)?

주어진 조건 값의 결과에 따라 프로그램이 다른 명령을 수행하도록 하는 일종의 조건문이다.

  • 모든 값, 범위를 기반으로 판단하는 if 문과 달리 정수 값이나 열거된 값 또는 문자, 문자열만을 사용할 수 있다.

  • 컴파일러를 통해 실행 경로를 설정하는 점프 테이블이라는 것이 만들어지게 되어서 많은 조건을 비교하여야 할 때, if else 보다 더 빠른 성능을 보이게 된다.

    → case의 수가 5개 이상이라면, 성능 차이가 보이기 시작한다.

  • if else에 비하여서 좋은 가독성을 가지고 있다.

switch 문

public static String monthCheck(int num){
        int days = 0;
        switch (num) {
            case 1 :
            case 3 :
            case 5 :
            case 7 :
            case 8 :
            case 10 :
            case 12 :
                days = 31;
                break;
            case 4 :
            case 6 :
            case 9 :
            case 11 :
                days = 30;
                break;
            case 2 :
                days = 28;
                break;
            default:
                days = -1;
        };
        return "입력하신 달은 "+days+"일 입니다.";
    }

 

if else 문 (비교 용)

public static String monthCheck(int num){
        int days = 0;
        if (num == 1 || num == 3 || num == 5 || num == 7 || num == 8 || num == 10 || num == 12){
            days = 31;
        } else if (num == 4 || num == 6 || num == 9 || num == 11){
            days = 30;
        } else if (num == 2){
            days = 28;
        } else {
            days = -1;
        }
        return "입력하신 달은 "+days+"일 입니다.";
    }

 

반복문?

어떠한 명령을 일정한 횟수만큼 반복하여 수행하도록 하는 명령문이다.

1부터 100까지를 더하는 코드를 여러 방법으로 작성해보았다.

 

 

while 문

  • 조건 식이 맞는 경우 실행되는 반복문이다. (bool 값을 통해 반복한다.)

구조

while(조건식){
        //do something
}

// 무한 루프 : 사용시 조건 검증과 break; 을 통해 탈출해야한다.
while(true){
        //do something
}
public static void whiles(){
    int total = 0;
    int loopCount = 1;
    while(loopCount <= 100){
        total += loopCount;
        ++loopCount;
    }
    System.out.println(total);
}

 

 

do / while 문

  • while 문과 비슷하지만 조건 식이 만족되지 않더라도 무조건 한 번은 실행되는 반복문이다.

구조

do{
        //do something
}while(조건식);

// 무한 루프 : 사용시 조건 검증과 break; 을 통해 탈출해야한다.
do{
        //do something
}while(true);

코드

public static void doWhiles(){
    int total = 0;
    int loopCount = 1;
    do {
        total += loopCount;
        ++loopCount;
    }while(loopCount <= 100);
    System.out.println(total);
}

 

 

for 문

  • 반복된 횟수가 고정된 경우 사용하거나, index 위치나 값이 필요한 경우 사용한다.

구조

for(조건식){ 
        //do something
}

// 무한 루프 : 사용시 조건 검증과 break; 을 통해 탈출해야한다.
// 해당 구문은 디컴파일 시 While(true)로 변경되어 있다.
for(;;){ 
        //do something
}

코드

public static void fors(){
    int total = 0;
    for (int loopCount = 0; loopCount <= 100; loopCount++) {
        total += loopCount;
    }
    System.out.println(total);
}

 

 

labeled for 문

  • 각각의 for 문에 대하여서 라벨을 부여함으로써 중첩 for문에서 조건에 따라 중단하거나 계속하게끔 사용하기 좋다.
  • 내부에 중첩된 for 문에 대해서도 라벨 부여가 가능하다.

구조

label:
        for(조건식){
                //do something
        }

혹은

label:
        for(조건식){
                //do something
                for(조건식){
                        //do something
                        break label;
                        // 혹은 continue;
                }
        }

코드

public static void labeledFors(){
    int total = 0;

        // 무한 루프
    loop1: for (;;){
        for (int inLoop=0;inLoop<=1000;inLoop++){
            total += inLoop;

                        // 100번을 반복하게 되면 loop1을 탈출한다. 
            if(inLoop==100) {
                break loop1;  
            }
        }
    }
    System.out.println(total);
}

 

 

Enhanced for 문 (for each)

  • index 값이 아닌 요소를 통한 값의 순회를 진행한다.
  • 가변적인 컬렉션의 값을 처리하기에 좋다.

구조

for(Type variable : collection<Type>, Type[] array){
        //do something
}

코드

public static void enhancedFors(){
    int total = 0;
    int[] numArr = {10,20,30,40,50,60,70,80,90,100};
    for (int num : numArr){
        total += num;
    }
    System.out.println(total);
}

 

 

HashTable, Vector, Stack의 Enumeration

  • Collection Framework가 만들어지기 전에 사용되던 인터페이스이다.

  • 순차 접근 시 컬랙션 객체의 내부가 수정되더라도 이를 무시하고, 끝까지 동작한다

    → Enumeration을 이용해서는 내부 요소를 수정할 방법이 없다. (읽기만 가능하다.)

    → 해당 컬랙션 내부의 수정 메서드를 이용하여야 한다.

Enumeration<String> enumeration = vector.elements();

// 읽어올 요소가 존재한다면, True 요소가 없다면 false를 반환한다.
enumeration.hasMoreElements()

// 다음 요소를 읽어올 때 사용한다.
enumeration.nextElement()

 

 

Collection의 Iterator()

Collection Framework 에서 사용되는 Enumeration을 보완한 인터페이스이다.

→ 요소를 제거하는 기능을 포함하였다. (remove)

  • Fail Fast Iterator (ArrayList, HashMap)

    • 순차적 접근이 끝나기 전에 객체에 변경이 일어날 경우 예외를 반환한다.

      → 동일한 자원의 수정 발생 시 데이터의 일관성을 보장하기 위함이다.

    • 내부적으로 변경, 수정된 횟수를 나타내는 modCount 필드가 있다.

      • 하나 이상의 요소가 제거된 경우

      • 하나 이상의 요소가 추가된 경우

      • 컬렉션이 다른 컬렉션으로 대체되었을 때

      • 컬렉션이 정렬될 때 등

        → 구조가 변경될 때마다 카운터가 증가하게 된다..

        → 데이터를 순회하는 동안 expectedModCount에 modCount 값을 저장하고 비교하며,

        → 두 개의 값이 달라질 경우 ConcurrentModificationException()를 발생시킨다.

        → next(), remove(), add(), remove(), forEachRemaining()에서 사용된다.

        → HashTable에도 expectedModCount, modCount를 사용한다.

  • Fail Safe Iterator (CopyOnWriteArrayList, ConcurrentHashMap)

    • Enumeration와 같이 내부가 수정되더라도 예외가 발생하지 않는다.

    • 사실은 컬렉션의 원본이 아닌 복제본을 순회하기 때문이다.

      → 복제된 컬렉션을 관리하기 위해 추가적인 메모리를 사용한다.

 

과제 0. JUnit 5 학습하세요.

 

JUnit 5를 만들게 된 이유? (JUnit 4의 단점)

  • IDE에 대한 강한 결합도를 해결하기 위하여

  • 부족했던 확장성의 해결

    → 하나의 @Runwith에 여러 Rule을 사용하여 확장하고, Runwith들이 결합되지 못했다.

  • 하나의 Jar에 포함되어 있던 코드를 분리하였다. (하나의 Jar의 큰 책임)

이전 버전의 문제점을 해결하며 좀 더 단순하고, 확장성 있게 만들기 위해 그런 선택을 하였다고 한다.

그 외에도 외부 라이브러리를 사용해야 했던 Parameter Test 등의 부가 기능을 공식적으로 지원한다.

//넘겨지는 Source의 수 만큼 테스트를 반복한다.

@ParameterizedTest(name = "{index} {displayName} SourceParam = {0}")
@ValueSource(strings = {"1", "2", "3"})
@NullAndEmptySource // CsvSource 등..
void repeatParameterTest(String Param) {
    System.out.println("Param = " + Param);
}

// 넘겨지는 정수 값 만큼 테스트 반복.
@RepeatedTest(10)
void repeatTest(String Param) {
    System.out.println("test");
}

혹시 Junit 4를 사용하고 있다면, Parameter Test가 필요한 경우

Pragmatists/JUnitParams

해당 라이브러리를 사용하면 된다.

 

그 외에도

 

접근 제어자 변경

  • public 접근 제어자가 필요했던 4 버전과 달리 5 버전은 패키지 범위에서 실행이 가능하다.

 

좋아진 확장성

  • Extension 하나로 여러 규칙을 통합, 조합 가능하다.

    → @ExtendWith, @RegisterExtension, Java ServiceLoader

 

분리된 Jar (모듈)

  • Junit 4의 Jar→Vintage(4 버전과의 호환성), Jupiter(5 버전 모듈), Platform(Extension, 실행, 관리 등)

 

다양해진 assert 방식

  • assertThat → assertThrows, assertEquals, assertTimeout, assertNotNull 등..

 

한 번에 여러 test를 실행 가능

  • 기존에 하나의 테스트가 실패하면 더 이상 진행되지 않는 Junit 4의 문제점을 해결

      assertAll(
              () -> assertNotNull(),
              () -> assertEquals(),
              () -> assertTrue(),
              () -> assertTimeout(),
      );

등이 변경되었다.

 

 

Junit 5의 Test Cycle

        // 모든 테스트가 실행되기 이전에 1번 호출된다.
    @BeforeAll
    public static void beforeAll() {
        System.out.println("AppTest.beforeAll");
    }

    // 모든 테스트가 실행된 이후에 1번 호출된다.
    @AfterAll
    public static void afterAll() {
        System.out.println("AppTest.afterAll");
    }

    // 각각의 테스트가 실행되기 이전에 호출된다.
    @BeforeEach
    public void beforeEach() {
        System.out.println("AppTest.beforeEach");
    }

    // 각각의 테스트가 실행된 이후에 호출된다.
    @AfterEach
    public void afterEach() {
        System.out.println  ("AppTest.afterEach");
    }

 

 

JUnit 5의 Dynamic Test

  • Junit 5부터는 테스트가 런타임 환경으로 생성되고 수행이 가능하게 되었다.
  • 이를 통해 외부 자원을 활용하고, 랜덤 데이터를 생성하여 활용할 수 있다.
@TestFactory
Stream<DynamicNode> dynamicTests() {
        return Stream.of("AAA","BBB","CCC","DDD")
                        .map(text -> dynamicTest("AAAEEETTT", () -> assertTrue(text.contains("AAA")));
}

 

 

Junit 5의 Tagging, Filtering

  • @Tag 주석을 통해 테스트 클래스 및 메서드에 태그를 지정할 수 있다.
@Tag("fast")
@Tag("User Test")...

 

 

Junit 5의 Test 순서 설정

  • @Order(정수 값) : 넘겨진 정수 값을 우선순위로 설정한다.

    → test_1 → test_2 → test_3...

@TestMethodOrder(OrderAnnotation.class)
class OrderedTest {

----------------------------

@Test
@Order(1)
void test_1() {
    // do someThing
}

@Test
@Order(2)
void test_2() {
    // do someThing
}

@Test
@Order(3)
void test_3() {
    // do someThing
}

 

 

JUnit 5의 Test 이름 표시

  • @DisplayName("test name")

    • DisplayNameGenerator 보다 우선적으로 적용된다.

    • method 위에 작성한다.

      @Test
      @DisplayName("AAA Test")
      void Arrange_Act_Assert() {
            // Arrange : 생성
            // Act : 조작
            // Assert : 결과 비교
      }
  • @DisplayNameGenerator

    • Class 내부의 모든 메서드에 적용된다.

    • Class 위에 작성한다.

      // 모든 밑줄 문자를 공백으로 바꾸는 static class
      @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
      
      // 표준 표시 생성 static class
      @DisplayNameGeneration(DisplayNameGenerator.Standard.class)

 

Junit 5의 테스트에 대한 환경 변수 설정

  • @EnabledIfEnvironmentVariable : 지정된 환경 변수 값이 지정된 정규식과 일치하는 경우 활성화
  • @EnabledIfSystemProperty : JVM 시스템에 따라서 테스트를 활성화
  • @EnabledOnJre : 지정된 JRE (Java Runtime Environment) 버전에서만 활성화
  • @EnabledForJreRange : min으로 지정된 jre와 max로 지정된 jre 버전 사이에서 활성화
  • @EnabledOnOs : 지정된 운영 체제에서만 활성화
@EnabledIfEnvironmentVariable(named = "GDMSESSION", matches = "ubuntu") // ununtu 서버에서 실행
@EnabledIfSystemProperty(named = "java.vm.vendor", matches = "Oracle.*") // Oracle jvm에서 실행
@EnabledForJreRange(min = JRE.JAVA_8, max = JRE.JAVA_13) // 8 ~ 13 버전의 자바에서 실행
@EnabledOnJre({JRE.JAVA_8, JRE.JAVA_9}) // 8, 9 버전의 자바에서만 실행
@EnabledOnOs({OS.WINDOWS, OS.LINUX}) // windows와 linux에서 실행

 

 

Junit5 Assertions

// assertEquals(A, B);
assertEquals("user", user.getUserName());

// assertTrue(A, B);
assertTrue("L", firstName.startsWith(user.getFirstName().charAt(0));

Exception exception = assertThrows(ArithmeticException.class, () -> calculator.divide(1, 0));
assertEquals("/ by zero", exception.getMessage());

// 시간 제한
assertTimeout(Duration.ofSeconds(1), () -> new user("Lob"));

// 시간이 초과되면 테스트 실패
assertTimeoutPreemptively(ofSeconds(1), () -> { Thread.sleep(5000); });

 

과제 1. live-study 대시 보드를 만드는 코드를 작성하세요.

package assignment.gitapi;

import org.kohsuke.github.*;

import java.io.IOException;
import java.util.*;

public class Application {

    private final String token = "tokenString";
    private GitHub github;

    public static void main(String[] args){

        Application app = new Application();

        try {
            app.run();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void run() throws IOException {

        // 연결
        connectGitApi();

        GHRepository ghRepository = github.getRepository("whiteship/live-study");
        // 참여자 이름, 참여 횟수
        Map<String, Integer> participant = new HashMap<>();
        // 모든 이슈를 가져온다.
        List<GHIssue> issues = ghRepository.getIssues(GHIssueState.ALL);

        //Find Issue
        for (GHIssue issue : issues) {
            // 각각의 Issue 에 존재하는 comment 들을 저장.
            List<GHIssueComment> commentList = issue.getComments();

            // 혹시 모를 유저 중복을 제거하기 위한 Set
            Set<String> nameList = new HashSet<>();

            addParticipantInSet(commentList, nameList);

            // 참여자 명단에서 비교한다.
            for (String s : nameList) {
                hasParticipantInSet(participant, s);
            }
        }
        printParticipantRate(participant);
    }

    private void hasParticipantInSet(Map<String, Integer> participant, String s) {
        if (!participant.containsKey(s)){
            participant.put(s, 1);
        } else {
            Integer integer = participant.get(s);
            participant.put(s, ++integer);
        }
    }

    private void addParticipantInSet(List<GHIssueComment> commentList, Set<String> name) throws IOException {
        for (GHIssueComment ghIssueComment : commentList) {
            name.add(ghIssueComment.getUser().getLogin());
        }
    }

    private void printParticipantRate(Map<String, Integer> participant) {
        participant.forEach((key, value)-> {
            double percent = (double) (value * 100) / 18;
            System.out.println(key+"  :  "+String.format("%.2f", percent)+"%");
        });
    }

    private void connectGitApi() throws IOException {
        github = new GitHubBuilder().withOAuthToken(token).build();
    }
}

Lob-dev/DashBoardDemo

 

Lob-dev/DashBoardDemo

Java Live Study assignment test(week 4). Contribute to Lob-dev/DashBoardDemo development by creating an account on GitHub.

github.com

 

과제 2. LinkedList를 구현하세요.

package assignment.linkedlist;

public class ListNode {

    private int elements;

    private ListNode next = null;

    public ListNode(int data) {
        elements = data;
    }

    public ListNode add(ListNode newElement){
        if (this.next == null){
            this.next = newElement;
            return this;
        }

        ListNode nextNode = this.next;
        while (nextNode.next != null){
            nextNode = nextNode.next;
        }

        nextNode.next = newElement;

        return this;
    }

    public ListNode add(ListNode head, ListNode nodeToAdd, int position){
        ListNode nextNode = head;

        for (int loop = 0; loop < position-1; loop++) {
            if (nextNode.next == null){ break; }
            nextNode = nextNode.next;
        }

        ListNode tmp = nextNode.next;
        nextNode.next = nodeToAdd;
        nodeToAdd.next = tmp;

        return this;
    }

    public ListNode remove(ListNode head, int positionToRemove){
        ListNode nextNode = head;

        for (int loop = 0; loop < positionToRemove-1; loop++) {
            nextNode = nextNode.next;
        }
        // 현재 시점의 nextNode 에서 next 가 지워져야할 node
        ListNode tmp = nextNode.next;
        nextNode.next = tmp.next;
        tmp = null;

        return this;
    }

    public boolean contains(ListNode head, ListNode nodeToCheck){
        ListNode nextNode = head;

        while (nextNode.next != null){
            if (nextNode.elements == nodeToCheck.elements){
                return true;
            }
            nextNode = nextNode.next;
        }

        return false;
    }

    public void printForEach(){
        ListNode nextNode = this;

        while (nextNode != null){
            System.out.println(nextNode.elements);
            nextNode = nextNode.next;
        }
    }

    public int size(){
        ListNode nextNode = this;

        int size = 0;
        while (nextNode != null){
            ++size;
            nextNode = nextNode.next;
        }

        return size;
    }
}

Lob-dev/DashBoardDemo

 

Lob-dev/DashBoardDemo

Java Live Study assignment test(week 4). Contribute to Lob-dev/DashBoardDemo development by creating an account on GitHub.

github.com

테스트

Lob-dev/DashBoardDemo

 

Lob-dev/DashBoardDemo

Java Live Study assignment test(week 4). Contribute to Lob-dev/DashBoardDemo development by creating an account on GitHub.

github.com

 

과제 3. Stack을 구현하세요.

package assignment.stack;

public class StackNode {

    private int[] elements;
    private int head = 0;
    private int size = 16;
    private int modifyCount = 0;

    public StackNode() {
        elements = new int[size];
    }

    public StackNode(int size) {
        elements = new int[this.size = size];
        System.out.println(this.size);
    }

    public boolean push(int data){
        if (modifyCount >= size){ return false; }
        elements[modifyCount] = data;
        head = modifyCount;
        ++modifyCount;
        return true;
    }

    public int pop(){
        if (head < 0) { return -1; }
        int res = elements[head];
        elements[head] = -1;
        head--;
        return res;
    }

    public void print(){
        for (int index : elements){
            if (index == 0 || index == -1){
                System.out.println("is Empty");
                break;
            }
            System.out.println(index);
        }
    }
}

Lob-dev/DashBoardDemo

 

Lob-dev/DashBoardDemo

Java Live Study assignment test(week 4). Contribute to Lob-dev/DashBoardDemo development by creating an account on GitHub.

github.com

테스트

Lob-dev/DashBoardDemo

 

Lob-dev/DashBoardDemo

Java Live Study assignment test(week 4). Contribute to Lob-dev/DashBoardDemo development by creating an account on GitHub.

github.com

 

과제 4. 앞서 만든 ListNode를 사용해서 Stack을 구현하세요.

package assignment.stack;

import assignment.linkedlist.ListNode;

import java.util.List;

public class ListStack {

    private ListNode node = null;
    private ListNode head;

    public void push(int data){
        if (node == null){
            node = new ListNode(data);
            head = node;
        } else {
            ListNode nextNode = node.next;
            while (nextNode.next != null){
                nextNode = nextNode.next;
            }
            nextNode.next = new ListNode(data);
            head = nextNode.next;
        }
    }

    public int pop(){
        ListNode nextNode = node;
        ListNode preNode = head;

        if (node.next == null){ node = null; }

        while (nextNode.next != null){
            preNode = nextNode;
            nextNode = nextNode.next;
        }

        int result = head.elements;
        head = preNode;
        preNode.next = null;

        return result;
    }

    public void print(){
        if (node == null){
            System.out.println("is empty");
        } else if (node.next == null){
            System.out.println(node.elements);
        } else{
            while (node.next != null){
                System.out.println(node.elements);
            }
        }

    }

    public static class ListNode{
        private int elements;
        private ListNode next = null;

        public ListNode(int data){
            elements = data;
        }
    }

}

Lob-dev/DashBoardDemo

 

Lob-dev/DashBoardDemo

Java Live Study assignment test(week 4). Contribute to Lob-dev/DashBoardDemo development by creating an account on GitHub.

github.com

테스트

Lob-dev/DashBoardDemo

 

Lob-dev/DashBoardDemo

Java Live Study assignment test(week 4). Contribute to Lob-dev/DashBoardDemo development by creating an account on GitHub.

github.com

 

(optional) 과제 5. Queue를 구현하세요.

배열 사용

package assignment.queue;

public class ArrayQueue {

    private int[] elements;
    private int size = 16;
    private final int head = 0;
    private int modifyCount = 0;

    public ArrayQueue() {
        elements = new int[size];
    }

    public ArrayQueue(int size) {
        elements = new int[size];
    }

    public boolean offer(int data){
        if (modifyCount >= size){ return false; }
        if (data < 0){ return false; }

        elements[modifyCount] = data;
        ++modifyCount;
        return true;
    }

    public int poll(){
        int res = elements[head];
        int modify = 0;
        for (int loop = 1; loop < modifyCount; loop++) {
            elements[loop-1] = elements[loop];
            modify = loop;
        }
        elements[modify] = -1;
        modifyCount = modify;
        return res;
    }

    public int size() {
        int size = 0;
        for (int index : elements){
            if (index == -1){ break; }
            if (index == 0){ break; }
            ++size;
        }
        return size;
    }

    public void print() {
        for (int index : elements){
            if (index == -1){ break; }
            if (index == 0){ break; }
            System.out.println(index);
        }
    }
}

Lob-dev/DashBoardDemo

 

Lob-dev/DashBoardDemo

Java Live Study assignment test(week 4). Contribute to Lob-dev/DashBoardDemo development by creating an account on GitHub.

github.com

테스트

Lob-dev/DashBoardDemo

 

Lob-dev/DashBoardDemo

Java Live Study assignment test(week 4). Contribute to Lob-dev/DashBoardDemo development by creating an account on GitHub.

github.com

 

ListNode 사용

package assignment.queue;

import assignment.stack.ListStack;

public class ListQueue{

    private ListNode node = null;

    private ListNode head;

    public ListQueue() {
    }

    public ListQueue(int element) {
        node = new ListNode(element);
        head = node;
    }

    public void offer(int data){
        if (node == null){
            node = new ListNode(data);
            head = node;
        } else {
            ListNode nextNode = node;
            while (nextNode.next != null){
                nextNode = nextNode.next;
            }
            nextNode.next = new ListNode(data);
        }
    }

    public int poll(){
        int result = head.elements;

        ListNode nextNode = head.next;
        head = null;
        head = nextNode;

        return result;
    }

    public int size() {
        int size = 0;
        ListNode nextNode = head;
        while (nextNode != null){
            ++size;
            nextNode = nextNode.next;
        }
        return size;
    }

    public void print() {
        if (head == null){
            System.out.println("is empty");
        } else if (head.next == null){
            System.out.println(node.elements);
        } else {
            ListNode nextNode = head;
            while (nextNode != null){
                System.out.println(nextNode.elements);
                nextNode = nextNode.next;
            }
        }

    }

    public static class ListNode{
        private int elements;
        private ListNode next = null;

        public ListNode(int data){
            elements = data;
        }
    }
}

Lob-dev/DashBoardDemo

 

Lob-dev/DashBoardDemo

Java Live Study assignment test(week 4). Contribute to Lob-dev/DashBoardDemo development by creating an account on GitHub.

github.com

테스트

Lob-dev/DashBoardDemo

 

Lob-dev/DashBoardDemo

Java Live Study assignment test(week 4). Contribute to Lob-dev/DashBoardDemo development by creating an account on GitHub.

github.com

 

참고 자료

Fail Fast and Fail Safe Iterators in Java - GeeksforGeeks

 

Fail Fast and Fail Safe Iterators in Java - GeeksforGeeks

A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

www.geeksforgeeks.org

Difference between Iterator and Enumeration in Java

 

Difference between Iterator and Enumeration in Java

Difference between Iterator and Enumeration in Java Iterator and Enumeration both are the cursors to traverse and access an element from the collection. They both belong to the collection framework. Enumeration was added in JDK1.0 and Iterator in the JDK.1

www.tutorialspoint.com

Loops in Java | Java For Loop - Javatpoint

 

Loops in Java | Java For Loop - Javatpoint

Loops in Java | Java for loop with java while loop, java for loop, java do-while loop, java for loop example, java for loop programs, labeled for loop, for each loop or advanced for loop, java infinite for loop example, java simple for loop, nested for loo

www.javatpoint.com

JUnit 5 User Guide

 

JUnit 5 User Guide

Although the JUnit Jupiter programming model and extension model will not support JUnit 4 features such as Rules and Runners natively, it is not expected that source code maintainers will need to update all of their existing tests, test extensions, and cus

junit.org

if(kakao)2020

 

if(kakao)2020

오늘도 카카오는 일상을 바꾸는 중

if.kakao.com

 

3주 차 시작합니다!

연산이란?

주어진 정보를 통해 일정한 규칙에 따라 어떤 값이나 결과를 구하는 과정을 의미한다.

 

연산자란?

연산을 진행하는 동안 사용되는 기호를 말한다.

연산 대상의 수나 연산 방식에 따라서 명칭이 나뉘게 된다.

 

피연산자란?

연산될 대상을 말하며. 변수, 상수, 리터럴 등을 의미한다.

 

단항 연산자 (Unary Operator)

연산이 수행될 피연산자가 1개인 경우 해당 연산자를 단항 연산자라고 한다.

  • 전위 증감, 후위 증감 연산자
  • 단항으로써 사용하는 +, - 연산자 (부호 연산자)
  • 비트 반전 ~ 연산자

이항 연산자 (Binary Operator)

연산이 수행될 피연산자가 2개인 경우 해당 연산자를 이항 연산자라고 한다.

  • 산술 연산자
  • 비트 연산자
  • 관계 연산자
  • 대입 연산자
  • 논리 연산자

삼항 연산자 (Ternary Operator)

연산이 수행될 피연산자가 3개인 경우 해당 연산자를 삼항 연산자라고 한다.

  • 조건 연산자 ( 조건식? True의 경우 반환될 식 : False의 경우 일시 반환될 식 )

 

산술 연산자 (Arithmetic Operator)

산술 연산자는 수치 계산을 실시하는 연산자를 말한다.

  • A + B : 덧셈 연산자 (정수형, 실수형 리터럴뿐만 아니라 문자열 연산에도 사용 가능하다.)

      // 기본적인 사용법
          int numA = 10;
          int numB = 10;
    
          System.out.println(numA + numB); // 20
    
          int i = numA + numB;
        System.out.println(i);
    • 문자열 더하기 연산

      String strA = "hello";
      strA += " World";
      System.out.println(strA); // hello world
    • 값의 범위가 다른 Type 간의 연산 (공통)

      // long과 int를 더하는 경우에는?
      long longA = 10l;
      int numC = 10;
      
      System.out.println(longA+numC);
      
      // 실제로는 int 가 long으로 Type Conversion이 된 것을 알 수 있다. - 2주차 내용
      System.out.println(longA + (long)numC);
      
      // long과 double를 더하는 경우에는?
      long longA = 10;
      double doubleA = 10.0;
      
      System.out.println(longA+doubleA);
      
      // 실제로는 long 이 double로 Numeric Promotion이 된 것을 알 수 있다.
      System.out.println((double)longA + doubleA);
      
  • A - B : 뺄셈 연산자

      int numA = 10;
      int numB = 10;
    
      System.out.println(numA - numB); 
    
      int j = numA - numB; 
      System.out.println(j); // 0 출력
  • A / B : 나눗셈 연산자

    나눗셈 연산과 나머지 연산의 경우 피연산자로 0을 사용하면 Exception이 발생한다.

      int numA = 10;
      int numB = 10;
    
      System.out.println(numA / numB); 
    
      int k = numA / numB;
      System.out.println("k = " + k); // 1 출력 
  • A % B : 나머지 연산자

      int numA = 11;
      int numB = 2;
    
      System.out.println(numA % numB); 
    
      int l = numA % numB;
      System.out.println("l = " + l); // 1 출력
  • A * B : 곱하기 연산자

      int numA = 11;
      int numB = 2;
    
      System.out.println(numA * numB); 
    
      int h = numA % numB;
      System.out.println("h = " + h); // 22 출력
  • ++N, --N : 전위 증감 연산자

      int numC = 10;
      numC = --numC;
      System.out.println("numC = " + numC);
    
      int numD = 10;
      numD = ++numD;
      System.out.println("numD = " + numD);
    
      // Decompile
      // 전위 증감 연산자는 내부적으로 A = A +- 1; 의 형식을 취하는 것을 알 수 있다.
    
      int numC = 10;
      int numC = numC - 1;
      System.out.println("numC = " + numC);
    
      int numD = 10;
      int numD = numD + 1;
      System.out.println("numD = " + numD);
    
  • N++, N-- : 후위 증감 연산자

      int numE = 10;
      System.out.println(numE--);
      System.out.println("numE = " + numE);
    
      int numF = 10;
      System.out.println(numF--);
      System.out.println("numF = " + numF);
    
      // Decompile
      // 우선 임시변수를 만들어서 해당 값을 복사한뒤 전달하고 반영된 값을 그 이후에 제공한다.
    
      int numE = 10;
      byte var10001 = numE; // 임시변수에 값 복사
      int numE = numE - 1; // 변수 연산
      System.out.println(var10001); // 임시변수 출력
      System.out.println("numE = " + numE); // 연산된 변수를 제공
    
      int numF = 10;
      var10001 = numF; 
      int numF = numF - 1;
      System.out.println(var10001);
      System.out.println("numF = " + numF);
    • Wrapper와 Primitive 간의 산술 연산

    • Wrapper Class* (Integer, Long, Double)와 Primitive Type 연산 시에는 Wrapper Class 피연산자가 Unboxing 되어 연산이 진행되고 다시 Boxing이 되는 등에 성능상 오버헤드가 발생한다.

      int numB = 10;       
      
      Integer numA = numB; //autoboxing
      
      numA = numA + numB; //unboxing 후 연산 -> 결과 반영 전 다시 autoboxing 진행

      그리고 Operand Stack에서 관리되는 Primitive TypeHeap에서 참조되는 Wrapper Type은 값에 접근하는 시간에 차이가 존재한다. (일반적으로 Wrapper의 Access 시간이 길다.)

    • Primitive 도 일정 값 이상의 경우, Constant Pool이라는 Stack 외부에 존재하는 공간에 저장된다.*

    • JVM 설정 중에 Primitive 값의 크기에 대한 설정이 있다고 한다.

    • 즉 프로그램의 환경적인 부분에 따라서 수치나 연산 시간 등이 달라질 수 있다.

 

비트 연산자?

  • A & B : AND 연산 ( A와 B의 비트에 대해서 AND 연산을 수행한다.)

      //양쪽의 비트가 1이면 1, 0이면 0, 0 과 1 인 경우에는 0을 나타낸다.
    
      int num = 15; // 1111
      int nums = 6; // 0110
                    // 0110 : AND 연산
    
      int i = num & nums;
      System.out.println("i = " + i); // 6
  • A | B : OR 연산 ( A와 B의 비트에 대해서 OR 연산을 수행한다.)

      //하나의 비트가 1이면 1, 양쪽의 비트가 0이면 0이다.
    
      int num = 15; // 1111
      int nums = 6; // 0110
                    // 1111 : OR 연산
    
      int i = num | nums;
      System.out.println("i = " + i); // 15
  • A ^ B : XOR 연산 ( A와 B의 비트에 대해서 XOR 연산을 수행한다.)

      //하나의 비트가 1이면 1, 양쪽의 비트가 0이면 0, 양쪽의 비트가 1이면 0이다.
    
      int num = 15; // 1111
      int nums = 6; // 0110
                    // 1001 : XOR 연산
    
      int i = num ^ nums;
      System.out.println("i = " + i); // 9
  • A << N : 시프트 연산자 ( A의 비트를 좌측으로 N만큼 이동한다.)

      //비트를 좌측으로 N만큼 이동하고 우측에서 N만큼의 영역을 0으로 채우게된다.
    
      int num = 15; // 1111
      int nums = 2;
    
      int i = num << nums; // 111100 = 좌측으로 비트를 2칸씩 이동.
      System.out.println("i = " + i);
  • A >> N : 시프트 연산자 ( A의 비트를 우측으로 N만큼 이동한다.)

      //비트를 우측으로 N만큼 이동하고 좌측에서 N만큼의 영역을 0으로 채우게된다.
    
      int num = 15; // 1111
      int nums = 2;
    
      int i = num >> nums; // 0011 = 우측으로 비트를 2칸씩 이동.
      System.out.println("i = " + i);
  • A >>> N : 부호가 없는 시프트 연산자 ( A의 2진수를 우측으로 비트를 N만큼 이동한다.)

      int num = -15; // 11111111111111111111111111110001
      int nums = 2;
    
      // 부호를 신경쓰지 않고 모든 비트 값들을 오른쪽으로 이동시킨 후에 왼쪽의 빈 공간은 모두 
      // 0 으로 채운다.
    
      int i = num >>> nums; 
      System.out.println("i = " + i); // 1073741820 = 00111111111111111111111111111100
    
      int j = -15 >> nums;         
      System.out.println("j = " + j); // -4 : 11111111111111111111111111111100 
  • ~A : 반전 연산자 ( A 내부의 비트 값을 반전시킨다.)

      int num = -15; // 11111111111111111111111111110001
    
      System.out.println(~num);   // 14 : 00000000000000000000000000001110

 

관계 연산자?

  • A == B : 동일성 비교 ( A와 B가 같다면?)

      int numA = 10;
      int numB = 10;
    
      boolean isSame = numA == numB; // boolean 값을 반환.
    
      if (isSame){
          System.out.println(isSame); // true
      }
    
      혹은
    
      if (numA == numB){
          System.out.println(isSame); // true
      }
  • A != B : 동일하지 않은 경우 ( A와 B가 같지 않다면?)

      int numA = 10;
      int numB = 9;
    
      boolean isSame = numA != numB;
    
      if (isSame){
          System.out.println(isSame); //true
      }
    
      또는
    
      if (numA != numB){
          System.out.println(isSame); //true
      }
    
      또는
    
      boolean isSame = numA == numB;
    
      if (!isSame){
          System.out.println(isSame); //false 
      }
  • A > B : 대소 관계 비교 ( A가 B보다 크다면?)

      int numA = 10;
      int numB = 9;
    
      boolean isSame = numA > numB;
    
      if (isSame){
         System.out.println(isSame); //true
      }
    
      if (numA > numB){
         System.out.println(isSame); //true
      }
  • A >= B : 대소관계 비교 ( A가 B보다 크거나 같다면?)

      int numA = 10;
      int numB = 10;
    
      boolean isSame = numA >= numB;
    
      if (isSame){
         System.out.println(isSame); //true
      }
    
      if (numA >= numB){
         System.out.println(isSame); //true
      }
  • A < B : 대소관계 비교 ( A가 B보다 작다면?)

      int numA = 9;
      int numB = 10;
    
      boolean isSame = numA < numB;
    
      if (isSame){ 
         System.out.println(isSame); //true
      }
    
      if (numA < numB){
         System.out.println(isSame); //true
      }
  • A <= B : 대소관계 비교 ( A가 B보다 작거나 같다면?)

      int numA = 10;
      int numB = 10;
    
      boolean isSame = numA <= numB;
    
      if (isSame){
         System.out.println(isSame); //true
      }
    
      if (numA <= numB){
         System.out.println(isSame); //true
      }

 

논리 연산자?

  • 조건식 1 && 조건식2 : 조건식1과 조건식 2를 모두 만족한다면?

      int numA = 10;
      int numB = 10;
      int numC = 10;
      int numD = 10;
    
      boolean bool = numA == numB && numC < numD; //false
    
      if (bool){
         System.out.println(bool);
      }else {
           **System.out.println(bool);
      }
    
      if (numA == numB && numC == numD){
         System.out.println(numA == numB && numC == numD); //true
      }
  • 조건식1 || 조건식2 : 조건식1 혹은 조건식2를 만족한다면?

      int numA = 10;
      int numB = 10;
      int numC = 10;
      int numD = 10;
    
      boolean bool = numA == numB || numC < numD; //true
    
      if (bool){
         System.out.println(bool); 
      }else {
         System.out.println(bool);
      }
    
      if (numA == numB || numC == numD){
         System.out.println(numA == numB && numC == numD); //true
      }
  • ! : 논리 반전 연산자 : != 같지않다면?, !< 작지않다면?

      int num = 10;
      String conn = null;
    
      boolean bool = num != 9;
    
      if (bool){
         System.out.println(bool);
      }else {
         System.out.println(bool);
      }
    
      if (conn != null){
         System.out.println("true");
      }else {
         System.out.println("false");
      }
  • JDK Assertion (JDK 1.4+)

    이전에 작성된 코드에서 사용된 assert라는 변수들과의 하위 호환성을 위해 기본적으로 비활성화되어 있다.

    ```java
    assert service != null; // true -> 아무 일도 발생하지 않는다.
                                                // false -> AssertionError (Unchecked Exception) 발생
    
    혹은
    
    assert service != null : "Service is Null"; // false 시 추가적으로 메세지를 제공한다.

 

instanceof

  • A instanceof B : (공변) 타입 검증 연산자, A가 B의 타입 혹은 하위 구현체인지 판단한다.
    • Reference Type 만 사용 가능하다.
public static void main(String[] args) {
    InstanceofExample example = new InstanceofExample();
    example.run();
}

public void run() {
    SomeClass someClass = new SomeClass();
    SomeClasz someClasz = new SomeClasz();
    SomeClassChild someClassChild = new SomeClassChild();

    typeCheck(someClass);      // is SomeClass
    typeCheck(someClasz);      // is SomeClasz
    typeCheck(someClassChild); // is SomeClass
}

public void typeCheck(Object obj){
    if (obj instanceof SomeClass){
        System.out.println("is SomeClass");
    }else if (obj instanceof SomeClasz){
        System.out.println("is SomeClasz");
    }
}

class SomeClass {

}
class SomeClassChild extends SomeClass{

}
class SomeClasz {

}

 

대입 연산자? (assignment(=) operator)

Primitive 변수에 값을 할당하기 위해 사용하거나 Reference의 참조 값을 할당하기 위해 사용한다.

  • 그 외에도 이항 연산자와 결합하여 사용할 수 있다.
int num = 4;
int variable;

variable = num; // variable = 4;
System.out.println("= 연산 : " + variable); // = 연산 : 4

variable += num; // variable = 4 + 4
System.out.println("+= 연산 : " + variable); // += 연산 : 8

variable -= num; // variable = 8 - 4
System.out.println("-= 연산 : " + variable); // -= 연산 : 4

variable *= num; // variable = 4 * 4
System.out.println("*= 연산 : " + variable); // *= 연산 : 16

variable /= num; // variable = 16 / 4
System.out.println("/= 연산 : " + variable); // /= 연산 : 4

variable %= num; // variable = 4 % 4 
System.out.println("%= 연산 : " + variable); // %= 연산 : 0

variable = 10;
variable &= 2; // variable = 10 & 2
System.out.println("&= 연산 : " + variable); // &= 연산 : 2

variable = 10;
variable |= 2; // variable = 10 | 2
System.out.println("|= 연산 : " + variable); // |= 연산 : 10

variable = 10;
variable ^= 2; // variable = 10 ^ 2
System.out.println("^= 연산 : " + variable); // ^= 연산 : 8

variable = 10;
variable <<= 2; // variable = 10 << 2
System.out.println("<<= 연산 : " + variable); // <<= 연산 : 40

variable = 10;
variable >>= 2; // variable = 10 >> 2
System.out.println(">>= 연산 : " + variable); // >>= 연산 : 2

variable = 10;
variable >>>= 2; // variable = 10 >>> 2
System.out.println(">>>= 연산 : " + variable); // >>>= 연산 : 2

 

Arrow operator? ( (parameter list) -> lambda body )

Java 8에 추가된 lambda 식을 지원하기 위해 사용되는 연산자이다.

// 이러했던 구문을
Runnable runnable = new Runnable() {
   @Override
   public void run() {
       System.out.println("Hello!");
   }
};

// 이렇게 축약할 수 있다.

// 하나의 식, 로직을 가지고 있다면 { } block 과 return도 생략 가능하다.
Runnable runnable = () -> System.out.println("Hello!");

// 그렇지 않다면 이런식으로 작성해야한다.
Runnable runnable = () -> {
    System.out.println("Hello!");
    helloLogic();
**};**

 

3항 연산자? ( Ternary Operator : 변수 = (조건)? true 인 경우 : false 인 경우)

삼항 연산자는 피연산자 3개를 사용하며, if-then-else 명령문의 축약형이라고 할 수 있다.

int num = 10;
String result;

if(num == 10){
        result = "true";
        System.out.println("result = " + result);
}else {
        result = "false;
        System.out.println("result = " + result);
}

result = (num == 10) ? "true" : "false";
System.out.println("result = " + result);

 

연산자 우선순위?

수식 내에 여러 연산자가 함께 등장할 때, 어느 연산자가 먼저 처리될 것인가를 결정합니다.

( ) 등으로 우선순위, 결합 방향에 따른 연산자의 처리 순서를 변경할 수도 있습니다.

 

연산자의 결합 규칙?

수식 내에 우선순위가 같은 연산자가 둘 이상 있을 때, 먼저 어느 연산을 수행할 것인가를 결정합니다.

int numA = 5;
int numB = 2;
int numC = 2;

// +, - 의 우선 순위가 동일하다.
// 결합 방향에 따라서 왼쪽부터 오른쪽으로 진행하게 된다.
int res = numA + numB - numC;

 

Java 13의 switch 연산자?

기존 switch 문법으로 만든 요일 반환식 (윤년을 앞선 로직에서 체크했다고 가정.)

public static String monthCheck(int num){
        int days = 0;
        switch (num) {
            case 1 :
            case 3 :
            case 5 :
            case 7 :
            case 8 :
            case 10 :
            case 12 :
                days = 31;
                break;
            case 4 :
            case 6 :
            case 9 :
            case 11 :
                days = 30;
                break;
            case 2 :
                days = 28;
                break;
            default:
                days = -1;
        };
        return "입력하신 달은 "+days+"일 입니다.";
    }

Java 12에서 switch는

  • case 라벨을 쉼표로 구분하여 사용하게끔 문법을 지원하게 되었다.
  • break을 통해 값을 반환할 수 있게끔 되었다.
public static String monthCheck(int num){
        int days = switch (num) {
            case 1, 3, 5, 7, 8, 10, 12 :
                break 31;
            case 4, 6, 9, 11 :
                break 30;
            case 2 :
                break 28;
            default:
                break -1;
        };
        return "입력하신 달은 "+days+"일 입니다.";
    }

혹은 이와 같이 람다 식을 사용할 수 있게 되었다.

public static String monthCheck(int num){
        int days = switch (num) {
            case 1, 3, 5, 7, 8, 10, 12 -> 31;
            case 4, 6, 9, 11 -> 30;
            case 2 -> 28;
            default -> -1;
        };
        return "입력하신 달은 "+days+"일 입니다.";
    }

Java 13에서 switch는

  • 기존에 사용하던 break이라는 키워드를 yield로 대체(확장) 하게 되었다.
public static String monthCheck(int num){
        int days = switch (num) {
            case 1, 3, 5, 7, 8, 10, 12 :
                yield 31;
            case 4, 6, 9, 11 :
                yield 30;
            case 2 :
                yield 28;
            default:
                yield -1;
        };
        return "입력하신 달은 "+days+"일 입니다.";
    }

또는

public static String monthCheck(int num){
        int days = switch (num) {
            case 1, 3, 5, 7, 8, 10, 12 -> 31;
            case 4, 6, 9, 11 -> 30;
            case 2 -> 28;
            default -> {
                                System.out.println("잘못 입력했습니다.");
                                yield -1;
                        }
        };
        return "입력하신 달은 "+days+"일 입니다.";
    }

이렇게 표현할 수 있다.

 

Java 12 에서는 해당 기능을 미리보기 기능으로 제공하였고, (활성화 필요)

Java 13 에서는 해당 식을 확장하였으며,

Java 14 에서는 해당 기능을 표준으로 제공하게 되었다.

 

 

참고 자료

+ Recent posts