Java

[JAVA] 자바의 신 16 - 20

오초의 기록 2022. 7. 16. 21:56

16장

Nested 클래스

  • 클래스 안의 클래스
  • 사용 이유 : 코드를 간단하게 표현하기 위함
  • 클래스 선언시 static 선언 여부
    • 선언 o : Static nested 클래스
    • 선언 x : 내부 클래스
  • 내부 클래스
    • 로컬 내부 클래스 (local inner class)
    • 익명 내부 클래스(이름이 없는 클래스) (anonymous inner class)

Nested 클래스를 만드는 이유 (p. 417)

  • Static Nested 클래스를 사용하는 이유 : 한 곳에서만 사용되는 클래스를 논리적으로 묶어서 처리할 필요가 있을 때
  • 내부 클래스를 사용하는 이유 : 캡슐화가 필요할 때( 예를 들어 A라는 클래스에 private 변수가 있다. 이 변수에 접근하고 싶은 B라는 클래스를 선언하고, B클래스를 외부에 노출시키고 싶지 않을 경우가 여기에 속한다). 즉, 내부 구현을 감추고 싶을 때를 말한다.
  • 소스의 가독성과 유지보수성을 높이고 싶을 때

Static nested 클래스의 특징

  • 내부 클래스는 감싸고 있는 외부 클래스의 어떤 변수도 접근할 수 있다. 심지어 private로 선언된 변수까지도 접근 가능하다.
  • Static nested 클래스를 그렇게 사용하는 것은 불가능하다.
public class OuterOfStatic {
    static class StaticNested {
        private int value = 0; 
        public int getValue(){
            return value; 
        }
        public void setValue(int value){
            this.value = value;
        }
    }
}
  • 내부에 있는 Nested 클래스는 별도로 컴파일할 필요가 없다. OuterOfStatic이라는 감싸고 있는 클래스를 컴파일하면 자동으로 컴파일되기 때문이다.
  • Nested 클래스는 이처럼 감싸고 있는 클래스 이름 뒤에 $ 기호를 붙인 후 Nested 클래스의 이름이 나온다.
  • OuterOfStatic.class OuterOfStatic$StaticNested.class

StaticNested 클래스의 객체 생성

public class NestedSample {
    public static void main(String[] args) {
        NestedSample sample = new NestedSample();
        sample.makeStaticNestedObject();
    }

    public void makeStaticNestedObject() {
        OuterOfStatic.StaticNested staticNested = new OuterOfStatic.StaticNested();
        staticNested.setValue(3);
        System.out.println(staticNested.getValue());
    }
}
  • 객체 생성은 감싸고 있는 클래스 이름 뒤에 .(점)을 찍고 쓰면 된다. 객체를 생성한 이후에 사용하는 방법은 일반 클래스와 동일하다.

내부 클래스와 익명 클래스 (p. 419)

public class OuterOfInner {
    class Inner {
        private int value = 0; 
        public int getValue(){
            return value;
        }
        public void setValue(int value){
            this.value = value;
        }
    }
}
public class InnerSample {
    public static void main(String[] args) {
        InnerSample sample = new InnerSample();
        sample.makeInnerObject();
    }
    public void makeInnerObject(){
        OuterOfInner outer = new OuterOfInner();
        OuterOfInner.Inner inner = outer.new Inner();
        inner.setValue(3);
        System.out.println(inner.getValue());
    }
}
  • Inner 클래스의 객체를 생성하기 전에는 먼저 Inner클래스를 감싸고 있는 OuterOfInner 라는 클래스의 객체를 만들어야만 한다. 여기서는 outer라는 객체다. 이 outer 객체를 통해서 Inner 클래스의 객체를 만들어 낼 수 있다.

내부 클래스를 만드는 이유

  • 캡슐화 때문이다. 하나의 클래스에서 어떤 공통적인 작업을 수행하는 클래스가 필요한데 다른 클래스에서는 그 클래스가 전혀 필요가 없을 때 이러한 내부 클래스를 만들어 사용한다. 내부 클래스는 GUI 관련 프로그램을 개발할 때 가장 많이 사용한다.

익명 클래스를 만드는 이유

  • 내부 클래스를 만드는 것보다 더 간단한 방법
  • public class AnonymousSample { public static void main(String[] args) { AnonymousSample sample = new AnonymousSample(); sample.setButtonListener(); } private void setButtonListener() { MagicButton button = new MagicButton(); button.setListener(new EventListener(){ public void onClick(){ System.out.println("Magic Button Clicked!!!"); } }); button.onClickProcess(); } }
  • 메소드를 호출하는 과정 내에 익명 클래스가 있는 것이기 때문에 이와 같이 소괄호를 닫고 세미콜론을 해 줘야만 한다.
  • 클래스 이름도 없고, 객체 이름도 없기 때문에 다른 클래스나 메소드에서는 참조할 수가 없다. 만약 객체를 해당 클래스내에서 재사용하려면, 다음과 같이 객체를 생성한 후 사용하면 된다.
 public void setButtonListenerAnonymousObject(){
        MagicButton button = new MagicButton();
        EventListener listener = new EventListener() {
            @Override
            public void onClick() {
                System.out.println("Magic Button Clicked");
            }
        };
        button.setListener(listener);
        button.onClickProcess();
    }
  • 클래스를 만들고, 그 클래스를 호출하면 그 정보는 메모리에 올라간다. 즉, 클래스를 많이 만들면 만들수록 메모리는 많이 필요해지고, 애플리케이션을 시작할 때 더 많은 시간이 소요되므로 ㄹ자바에서는 이렇게 간단한 방법으로 객체를 생성할 수 있도록 하였다.
  • 익명 클래스나 내부 클래스는 모두 다른 클래스에서 재사용할 일이 없을 때 만들어야 한다.

Nested 클래스의 특징

package chapter16;

public class NestedValueReference {
    public int publicInt = 0;
    protected int protectedInt = 1;
    int justInt = 2;
    private int privateInt = 3;
    static int staticInt = 4;

    static class StaticNested {
        public void setValue(){
            staticInt = 14;
        }
    }
    class Inner {
        public void setValue(){
            publicInt = 20;
            protectedInt = 21;
            justInt = 23;
            privateInt = 33;
            staticInt = 24;
        }
    }
    public void setValue(){
        EventListener listener = new EventListener() {
            public void onClick() {
                publicInt = 20;
                protectedInt = 21;
                justInt = 23;
                privateInt = 33;
                staticInt = 24;
            }
        };
    }
}
  • Static Nested 클래스에서는 감싸고 있는 클래스의 static 변수만 참조할 수 있다. StaticNedsted 클래스가 static 으로 선언되어 있기 때문에 부모 클래스에 static 하지 않은 변수를 참조할 수는 없다.
  • static nested 클래스와는 다르게, 내부 클래스와 익명 클래스는 감싸고 있는 클래스의 어떤 변수라도 참조할 수 있다.
public class ReferenceAtNested {
    static class StaticNested{
        private int staticNestedInt = 99; 
    }
    class Inner {
        private int innerValue= 100;
    }
    public void setValue(int value){
        StaticNested nested = new StaticNested();
        nested.staticNestedInt = value;
        Inner inner = new Inner();
        inner.innerValue = value;
    }
}
  • 감싸고 있는 클래스는 Static Nested 클래스의 인스턴스 변수나 내부 클래스의 인스턴스 변수로 접근 가능하다. 그 값이 private라고 할지라도 모두 접근할 수 있다.

17장

어노테이션이란?

  • @
  • Annotation
  • 메타데이터(Metadata)
  • 사용
    • 컴파일러에게 정보를 알려주거나
    • 컴파일할 때와 설치(deployment) 시의 작업을 지정하거나
    • 실행할 때 별도의 처리가 필요할 때
  • 클래스, 메소드, 변수 등 모든 요소에 선언할 수 있다.

미리 정해져 있는 어노테이션

  • @Override
  • @Deprecated
  • @SupressWarnings

@Override

  • 해당 메소드가 부모 클래스에 있는 메소드를 Override 했다는 것을 명시적으로 선언
public class Parent {
    public Parent(){
        System.out.println("Parent Constructor");
    }
    public Parent(String name){
        System.out.println("Parent(String) Constructor");
    }
    public void printName(){
        System.out.println("printName() - Parent");
    }
}

public class AnnotationOverride extends Parent{
    @Override
    public void printName(String args){ //--error
        System.out.println("AnnotationOverride");
    }

    @Override
    public void printName(){
        System.out.println("AnnotationOverride");
    }
}

@Deprecated

  • 미리 만들어져 있는 클래스나 메소드가 더 이상 사용되지 않는 경우
public class AnnotationDeprecated {
    @Deprecated
    public void noMoreUse(){

    }
}

public class AnnotationSample {
    public void useDeprecated(){
        AnnotationDeprecated child = new AnnotationDeprecated();
        child.noMoreUse();//'noMoreUse()' is deprecated
    }
}
  • 컴파일 결과에는 "경고"만 있고 "에러"는 없다
  • 하위 호환성을 위해서 Deprecated로 선언하는 것은 꼭 필요하다.

@ SupressWarnings

  • 컴파일러가 경고를 알리는 경우가 있는데 일부러 이렇게 코딩한 거니까 경고를 해 줄 필요가 없음을 알려주는 경우 사용
public class AnnotationSample {
    @SuppressWarnings("deprecation")
    public void useDeprecated(){
        AnnotationDeprecated child = new AnnotationDeprecated();
        child.noMoreUse();
    }
}

메타 어노테이션 (Meta annotaiton)

  • 어노테이션을 직접 선언할 때 사용

@Target

  • 어노테이션을 어떤 것에 적용할지를 선언할 때 사용한다.
  • Target 괄호 안에 적용 대상을 지정한다.
  • @Target(ElementType.METHOD)
요소 타입 대상
CONSTRUCTOR 생성자 선언시
FIELD enum 상수를 포함한 필드(field) 값 선언시
LOCAL_VARIABLE 지역 변수 선언시
METHOD 메소드 선언시
PACKAGE 패키지 선언시
PARAMETER 매개 변수 선언시
TYPE 클래스, 인터페이스, enum 등 선언시

@Retentaion

  • 얼마나 오래 어노테이션 정보가 유지되는지를 다음과 같이 선언한다.
  • 괄호 안에 지정하는 적용 가능한 대상
  • @Retention(RetentionPolicy.RUNTIME)
  대상
SOURCE 어노테이션 정보가 컴파일시 사라짐
CLASS 클래스 파일에 있는 어노테이션 정보가 컴파일러에 의해서 참조가 가능함. 하지만, 가상 머신(Virtual Machine)에서는 사라짐
RUNTIME 실행시 어노테이션 정보가 가상 머신에 의해서 참조 가능

@Documentated

  • 해당 "어노테이션에 대한 정보가 Javadocs(API) 문서에 포함된다는 것"을 선언

@Inherited

  • 모든 자식 클래스에서 부모 클래스의 어노테이션을 사용 가능하다는 것을 선언

@interface

  • 이 어노테이션은 어노테이션을 선언할 때 사용한다.

어노테이션 선언

java.lang.annotation

  • 어노테이션 관련 클래스들은 해당 패키지에 선언되어 있다.
@Target(ElementType.METHOD) // -- 1
@Retention(RetentionPolicy.RUNTIME) // -- 2
public @interface UserAnnotation { // -- 3
    public int number();
    public String text() default "This is first annotation"; // -- 4
}
    1. 메소드에 사용할 수 있다고 지정
      • 클래스 선언시, 메소드 선언시에 어노테이션 사용할 수 있도록 하려면
         @Target({ElementType.METHOD, ElementType.TYPE})
    1. 실행시에 이 어노테이션을 참조
    1. @UserAnnotation으로 어노테이션이 사용 가능해진다.
    1. default가 있으면 값을 지정하지 않아도 default 값으로 지정된다.
public class UserAnnotationSample {
    @UserAnnotation(number=0)
    public static void main(String args[]){
        UserAnnotationSample sample = new UserAnnotationSample();
    }
    @UserAnnotation(number=1)
    public void annotationSample1(){

    }
    @UserAnnotation(number=2,text="second")
    public void annotationSample2(){

    }
    @UserAnnotation(number=3,text="third")
    public void annotationSample3(){

    }
}

어노테이션에 선언된 값 확인

public class UserAnnotationCheck {
    public static void main(String[] args) {
        UserAnnotationCheck sample = new UserAnnotationCheck();
        sample.checkAnnotations(UserAnnotationSample.class);
    }
    public void checkAnnotations(Class useClass){
        Method[] methods = useClass.getDeclaredMethods(); // -- 1 
        for(Method tempMethod:methods){
            UserAnnotation annotation = tempMethod.getAnnotation(UserAnnotation.class); // -- 2
            if(annotation!=null){
                int number = annotation.number(); // -- 3
                String text = annotation.text(); // -- 3
                System.out.println(tempMethod.getName() + "() : number = " + number + ", text = "+ text);
            }else {
                System.out.println(tempMethod.getName()
                + "() : annotation is null.");
            }
        }
    }
}
    1. Class 클래스에 선언되어 있는 getDeclaredMethods() 메소드를 호출하면, 해당 클래스에 선언되어 있는 메소드들의 목록을 배열로 리턴한다.
    1. Method 클래스에 선언되어 있는 getAnnotation()이라는 메소드를 호출하면, 해당 메소드에 선언되어 있는 매개 변수로 넘겨준 어노테이션이 있는지 확인하고, 있을 경우 그 어노테이션의 객체를 리턴해준다.
    1. 어노테이션에 선언된 메소드를 호출하면, 그 값을 리턴해준다.

어노테이션도 상속이 안돼요

  • 미리 만들어놓은 어노테이션을 확장하는 것은 불가능하다.
  • extends 예약어 사용 불가

Lombok

  • 롬복을 사용하면 간단히 선언만으로도 getter 메소드와 setter 메소드를 생성해준다.

19장

자바에서 사용되는 다른 용어들

  • JDK : Java Development Kit
  • Java SE : Java Standard Edition
  • JRE : Java Runtime Environment
    • 자바를 실행할 수 있는 환경의 집합
    • 자바에서 제공하는 라이브러리들이 칸칸이 쌓여 있음

자바 언어의 특징

  • It should be "simple, object-oriented and familiar" (자바는 "단순하고, 객체지향적이며, 친숙"해야 한다.)
  • It should be "robust and secure" (자바는 "견고하고, 보안상 안전"하다.)
    • 자바는 컴파일할 때와 실행할 때 문법적 오류에 대한 체크를 한다.
  • It shoud be "architecture-netural and portable" (자바는 "아키텍처에 중립적이어야 하며 포터블" 해야 한다.)
    • 자바는 아키텍처에 중립적인 바이트 코드를 생성한다. 자바의 버전만 동일하다면, 동일한 프로그램은 어떤 플랫폼에서도 동일한 결과가 나오며, 호환성 문제가 발생하지 않는다( JVM 덕분 )
  • It should execute wite "high performance" (자바는 "높은 성능"을 제공해야 한다. )
  • It should be "interpreted, threaded, and dynamic" (자바는 "인터프리트 언어이며, 쓰레드를 제공하고, 동적인 언어"이다.)

자바의 버전별 차이

JDK 1.0

JDK 1.1

JDK 1.2

- Collections라는 프레임웍 추가

- JIT

  • Just-In-Time 의 약자
  • 어떤 메소드의 일부 혹은 전체 코드를 네이티브 코드로 변환하여 JVM에서 번역하지 않도록 함으로써 보다 빠른 성능을 제공하는 기술
  • 동적 변환 (dynamic translation)
  • 명칭이 컴파일러지만, 실행시에 적용되는 기술
  • 인터프리터(interpret) 방식 + 정적(static) 컴파일 방식 = 두 가지를 혼합한 것
    • 인터프리터 방식 : 프로그램을 실행할 때마다 컴퓨터가 알아 들을 수 있는 언어로 변환하는 작업
    • 정적컴파일 방식 : 실행하기 전에 컴퓨터가 알아 들을 수 있는 언어로 변환하는 작업을 미리 실행
  • 변환 작업은 인터프리터에 의해서 지속적으로 수행되지만, 필요한 코드의 정보는 캐시에 담아두었다가(메모리에 올려두었다가) 재사용
  • javac : 텍스트로 만든 java 파일을 어떤 OS에서도 수행될 수 있도록 바이트 코드라는 파일로 만든 것이고, 컴퓨터가 알아먹을 수 있도록 하려면 다시 변환 작업이 필요한데, 이 변환 작업을 JIT 컴파일러가 수행함

자바 프로그램이 수행되는 절차

자바 소스 코드 -> 자바 컴파일러 -> 컴파일 된 Bytecode -> JVM -> 기계 코드 -> 하드 웨어 및 OS 
  • "JVM -> 기계 코드" 로 변환되는 부분을 JIT에서 수행하는 것

JDK 1.3

- HotSpot JVM

  • 종류
    • HotSpot 클라이언트 컴파일러
      • CPU 코어가 하나 뿐인 사용자를 위해 만들어짐
    • HotSpot 서버 컴파일러
      • 코어가 많은 장비에서 사용하기 위해 만들어짐
  • 기준
    • 기본적으로 자바가 시작할 때 알아서 클라이언트 장비인지 서버 장비인지를 확인한다.
    • 아래 조건 만족시 JVM은 서버 컴파일러 선택
      • 2개 이상의 물리적 프로세스
      • 2GB 이상의 물리적 메모리
  • 명시적 지정
    • 클라이언트 JVM
      java -client Calculator
      • 서버 JVM
        java -server Calculator
  • 옵션 지정
    • JVM의 시작 메모리 크기를 지정 : -Xms
      java -server -Xms512m Calculator

JDK 1.4

  • 정규 표현식
  • NIO

JDK 5

  • 보다 안전하게 컬렉션 데이터를 처리할 수 있는 제너릭(generic) 추가
  • 어노테이션(annotation)이라고 불리는 메타데이터(metadata) 기능 추가
  • 기본 자료형과 그 기본 자료형을 객체로 다루는 클래스 간의 데이터 변환이 자동으로 발생하는 autoboxing 및 unboxing 기능 추가
  • 상수 타입을 나타내는 enum 추가
  • 매개 변수의 개수를 가변적으로 선언할 수 있는 varargs 추가
  • for 루프에 세미콜론이 아닌 콜론으로 구분하여 배열이나 컬렉션 타입에 저장되어 있는 데이터를 순차적으로 꺼내는 향상된 for 루프 추가
  • import 앞에 static 붙여 정적 import가 가능하도록 해 주는 static import 추가
  • 쓰레드 처리를 쉽게 할 수 있는 concurrent 패키지(java.util.concurrent) 추가
  • 스트림이나 버퍼로 들어오는 데이터의 분석(parse)을 보다 간편하게 할 수 있는 Scanner 클래스 추가

JDK 6

JDK 7

JDK 8

  • 람다 표현식

JVM

  • Java Virtual Machine
  • 자바 가상 머신
  • 자바 프로그램이 수행되는 프로세스
  • JVM 위에서 애플리케이션이 동작
  • JVM에서 작성한 프로그램을 찾고 실행하는 일련의 작업이 수행

GC

  • Garbage Collector
  • 가비지 컬렉터
  • 메모리 관리를 JVM이 알아서 하기 때문에 자바의 메모리 관리는 개발자가 하지 않아도 된다.
  • JVM 내에서 메모리 관리를 해주는 것이 바로 "가비지 컬렉터"이다.
  • Java7부터 공식적으로 사용할 수 있는 G1 라는 가비지 컬렉터를 제외한 나머지 JVM은 위와 같이 영역을 나누어 힙(Heap)이라는 공간에 객체들을 관리한다.

자바의 힙 영역

  • Young
    • Eden : 객체를 생성하자마자 저장되는 장소
    • 2개의 Survivor 영역

자바에서 메모리가 살아가는 과정

  • 마이너 GC or 영 GC(컬렉션)
    • Eden 영역에서 객체가 생성된다.
    • Eden 영역이 꽉 차면 살아있는 객체만 Survivor 영역으로 복사되고, 다시 Eden 영역을 채우게 된다.
    • Survivor 영역이 꽉 차게 되면 다른 Survivor 영역으로 객체가 복사된다. 이때, Eden 영역에 있는 객체들 중 살아있는 객체들도 다른 Survivor 영역으로 간다. 즉, Survivor 영여그이 둘 중 하나는 반드시 비어있어야 한다.
  • 메이저 GC or 풀 GC
    • 오래 살아있는 객체들은 Old 영역으로 이동한다.
    • Old 영역이 꽉차면 GC가 발생함.
  • 영 GC 가 풀 GC 보다 빠르다
    • 더 작은 공간이 할당되고, 객체들을 처리하는 방식도 다르기 때문이다.
    • 전체의 힙 영역을 영 영역으로 만들면 장애로 이어질 확률이 매우 높다.

5가지 가비지 컬렉터

  • Serial GC
    • WAS로 사용하는 JVM에서 사용하면 안 되는 GC.
    • 이 GC 방식은 -client 옵션을 지정했을 때 사용된다. 즉, 클라이언트용 장비에 최적화된 GC이기 때문에 WAS에서 이 방식을 사용하면 GC 속도가 매우 느려 웹 애플리케이션이 엄청 느려진다.
  • Parallel Young Generation Collector
  • Parallel Old Generation Collector
  • Concurrent Mark & Sweep Collector(CMS)
  • G1(Garbage First)

20장. Java.lang 패키지

java.lang 패키지에 정의되어 있는 "에러"

  • OutOfMemoryError(OOME)
    • 메모리가 부족하여 발생하는 에러
  • StackOverflowError
    • 호출된 메소드의 깊이가 너무 깊을 때 발생한다.
    • Stack 이라는 영역에 어떤 메소드가 어떤 메소드를 호출했는지에 대한 정보를 관리한다. 스택에 쌓을 수 있는 메소드 호출 정보의 한계를 넘어설 때 발생

숫자를 처리하는 클래스들

  • 기본 자료형
    • 힙 영역에 저장되지 않고, 스택 영역에 저장되어 관리된다.
  • Wrapper 클래스
    • Byte, Short, Integer, Long, Float, Double, Character, Boolean
    • 모두 Number와 abstract 클래스를 확장(extends) 한다.
  • Character, Boolean
    → 겉으로 보기에는 참조자료형, 컴파일러에서 자동으로 형 변환해주므로 기본 자료형처럼 사용 가능
  • 공통 메소드 (Character 제외)
    • parse타입이름()
      • static 메소드 : 객체 생성 없이 바로 사용 가능
      • 문자열을 숫자 타입으로 변환
      • 기본 자료형을 리턴
    • valueOf()
      • static 메소드 : 객체 생성 없이 바로 사용 가능
      • 문자열을 숫자 타입으로 변환
      • 참조 자료형을 리턴
public class JavaLangNumber {
    public static void main(String[] args) {
        JavaLangNumber sample = new JavaLangNumber();
        sample.numberTypeCheck();
    }
    public void numberTypeCheck(){
        String value1 = "3";
        String value2 = "5";
        byte byte1 = Byte.parseByte(value1);
        byte byte2 = Byte.parseByte(value2);
        System.out.println(byte1 + byte2);//8

        Integer refInt1 = Integer.valueOf(value1);
        Integer refInt2 = Integer.valueOf(value2);
        System.out.println(refInt1 + refInt2 +"7");//87
    }
}

숫자를 처리하는 참조형을 만든 이유

  • 참조 자료형 중에서 Byte, Short, Integer, Long, Float, Double은 필요시 기본 자료형처럼 사용할 수 있다. new를 사용하여 객체를 생성하지 않아도 값 할당 o.
 public void numberTypeCheck2(){
        Integer refInt1;
        refInt1 = 100;
        System.out.println(refInt1.doubleValue());
    }
  • 매개 변수를 참조 자료형으로만 받는 메소드 처리
  • 제너릭과 같이 기본 자료형을 사용하지 않는 기능을 사용하기 위해서
  • MIN_VALUE(최소값)나 MAX_VALUE(최대값)와 같이 클래스에 선언된 상수 값을 사용하기 위해서(boolean 클래스 제외)
  • 문자열을 숫자로, 숫자를 문자열로 쉽게 변환하고, 2,8,10,16 진수 변환을 쉽게 처리하기 위해서
public void numberMinMaxCheck(){
        System.out.println("Byte min = "+ Byte.MIN_VALUE + " Byte max = " +Byte.MAX_VALUE);
        System.out.println("Short min = "+ Short.MIN_VALUE + " Short max = " +Short.MAX_VALUE);
        System.out.println("Integer min = "+ Integer.MIN_VALUE + " Integer max = " +Integer.MAX_VALUE);
        System.out.println("Long min = "+ Long.MIN_VALUE + " Long max = " +Long.MAX_VALUE);
        System.out.println("Float min = "+ Float.MIN_VALUE + " Float max = " +Float.MAX_VALUE);
        System.out.println("Double min = "+ Double.MIN_VALUE + " Double max = " +Double.MAX_VALUE);
        System.out.println("Character min = "+ (int)Character.MIN_VALUE + " Character max = " +(int)Character.MAX_VALUE);

        /*
        Byte min = -128 Byte max = 127
        Short min = -32768 Short max = 32767
        Integer min = -2147483648 Integer max = 2147483647
        Long min = -9223372036854775808 Long max = 9223372036854775807
        Float min = 1.4E-45 Float max = 3.4028235E38
        Double min = 4.9E-324 Double max = 1.7976931348623157E308
        Character min = 0 Character max = 65535
        */
    }
public void integerMinMaxCheckBinary(){
        //2진수
        System.out.println("Integer BINARY min=" + Integer.toBinaryString(Integer.MIN_VALUE));
        System.out.println("Integer BINARY min=" + Integer.toBinaryString(Integer.MAX_VALUE));
        //16진수
        System.out.println("Integer HEX min=" + Integer.toHexString(Integer.MIN_VALUE));
        System.out.println("Integer HEX min=" + Integer.toHexString(Integer.MAX_VALUE));

        /*
        Integer BINARY min=10000000000000000000000000000000
        Integer BINARY min=1111111111111111111111111111111
        Integer HEX min=80000000
        Integer HEX min=7fffffff
        */
    }

System 클래스

  • 생성자 없음
  • System 클래스는 시스템에 대한 정보를 확인하는 클래스
  • 3개의 static 변수
선언 및 리턴 타입 변수명 설명
static PrintStream err 에러 및 오류를 출력할 때 사용한다
static InputStream in 입력값을 처리할 때 사용한다
static PrintStream out 출력값을 처리할 때 사용한다
  • static 메소드
    • println()
  • 변수와 메소드가 모두 static으로 선언되어 있어서 별도의 클래스 객체를 생성할 필요가 없음
  • Printstream, InputStream은 java.io 패키지에 선언

제공 메소드

시스템 속성(Property) 값 관리

리턴 타입 메소드 이름 및 매개 변수 설명
static String clearProperty(String key) key에 지정된 시스템 속성을 제거한다.
static Properties getProperties() 현재 시스템 속성을 Properties 클래스 형태로 제공한다.
static String getProperties(String key) key에 지정된 문자열로 된 시스템 속성값(value)을 얻는다.
static String getProperties(String key, String def) key에 지정된 문자열로 된 시스템 속성값(value)을 얻고, 만약에 없으면, def에 지정된 값을 리턴한다.
static void setProperties(Properties props) Properties 타입으로 넘겨주는 매개 변수에 있는 값들을 시스템 속성에 넣는다.
static String setProperty(String key, String value) key에 지정된 시스템 속성의 값을 value로 대체한다.
  • Properties는 java.lang 패키지에 속하며, Hashtable의 상속을 받은 클래스
  • Properties라는 클래스의 객체는 key-value로 묶여 있는 여러 개의 데이터를 제공한다고 알고 있으면 된다.
  • 필요 여부와 상관없이 자바 프로그램을 실행하면 Properties 객체가 생성되며, 그 값은 언제, 어디서 든지 같은 JVM 내에서는 꺼내서 사용할 수있다.
  • Properties는 추가할 수도 있고, 변경할 수도 있다.
public class JavaLangSystem {
    public static void main(String[] args) {
        JavaLangSystem sample = new JavaLangSystem();
        sample.systemPropertiesCheck();
    }

    public void systemPropertiesCheck(){
        System.out.println("java.version = "  + System.getProperty("java.version"));//java.version = 11.0.13
    }
}

시스템 환경(Environment) 값 조회

  • 환경값 env라는 것은 변경하지 못하고 읽기만 할 수 있다.
  • 이 값들은 대부분 OS나 장비와 관련된 것
리턴 타입 메소드 이름 및 매개 변수 설명
static Map<String,String> getenv() 현재 시스템 환경에 대한 Map형태의 리턴값을 받는다.
static String getenv(String name) 지정한 name에 해당하는 값을 받는다.
 System.out.println("JAVA_HOME = " + System.getenv("JAVA_HOME"));//JAVA_HOME = C:\Program Files\Java\jdk-11.0.13

GC 수행(절대 사용 x)

리턴 타입 메소드 이름 및 매개 변수 설명
static void gc() 가비지 컬렉터를 실행한다.
static void runFinalization() GC 처리를 기다리는 모든 객체에 대하여 finalize() 메소드를 실행한다.
  • 메모리 처리를 개발자가 별도로 하지 않는다.
  • 직접 호출하지 않아도 JVM이 더 이상 필요 없는 객체를 처리하는 GC 작업과 finalization 작업을 실행함

JVM 종료(절대 사용 x)

리턴 타입 메소드 이름 및 매개 변수 설명
static void exit(int status) 현재 수행중인 JVM을 멈춘다.

현재시간 조회

  • currentTimeMillis()
    • 리턴 타입 : static long
    • 현재 시간을 밀리초 단위로 리턴한다.
    • 현재 시간을 나타낼 때 사용
    • UTC(Universal time 기준으로 1970년 1월 1일 00:00 부터 지금까지의 밀리초(1/1000) 단위의 차이를 출력한다.
  • nanoTime()
    • 리턴 타입 : static long
    • 현재시간을 알아내는 용도 아님
    • 시간 차이를 측정하기 위한 용도임
    • 나노초 (1/1,000,000,000초) 로 시간 제공
public void numberMinMaxElapseCheck(){
        JavaLangNumber numberSample = new JavaLangNumber();
        long startTime = System.currentTimeMillis();
        long startNanoTime = System.nanoTime();
        numberSample.numberMinMaxCheck();
        System.out.println("Milli second = " + (System.currentTimeMillis()-startTime));//Milli second = 0
        System.out.println("Nano second = " + (System.nanoTime() - startNanoTime));//Nano second = 10081100
    }

System.out

  • print(), println(), printf(), format(), write()
  • print() , println()
    • 차이점
      • println()만 줄바꿈
      • println()만 매개변수가 없는 메소드 존재
    • 공통점
      • byte 타입이나 short 타입을 매개변수로 받는 메소드 선언되어 있지 않지만, 넘겨 주면 int 타입을 매개 변수로 받는 메소드에서 알아서 처리해줌
public class JavaLangSystemPrint {
    public static void main(String[] args) {
        JavaLangSystemPrint sample = new JavaLangSystemPrint();
        sample.printStreamCheck();
    }
    public void printStreamCheck(){
        byte b = 127;
        short s = 32767;
        System.out.println(b);
        System.out.println(s);
        printInt(b);
        printInt(s);
        /*
        127
        32767
        127
        32767
        */
    }

    public void printInt(int value){
        System.out.println(value);
    }
}
    public void printNull(){
        Object obj = null;
        System.out.println(obj);// == String.valueOf(obj)
        System.out.println(obj.toString());//NullPointerException
        System.out.println(obj + "is object's value"); // == new StringBuilder().append(obj).append(" is object's value)
    }
  • println(), print() 메소드
    • toString() 메소드 결과를 출력 x
    • valueOf()라는 static 메소드를 호출하여 결과를 받은 후 출력 o