반응형

목표

자바가 제공하는 다양한 연산자를 학습하세요.

학습할 것

  • 산술 연산자
  • 비트 연산자
  • 관계 연산자
  • 논리 연산자
  • instanceof
  • assignment(=) operator
  • 화살표(->) 연산자
  • 3항 연산자
  • 연산자 우선 순위
  • (optional) Java 13. switch 연산자

 

 

  •  

산술 연산자

  • Binary Operator(이항)

    • +, -, *, /, %(Modulo)
    • ArithmeticException 발생 가능
      • Divide by zero
      • Modulo by zero 

비트 연산자

  • Binary Operator(이항)
    • &(AND)
    • |(OR)
    • ^(XOR)
    • >> (right SHIFT)
    • << (left SHIFT)
    • >>> (unsigned right SHIFT) : 비트값을 오른쪽으로 이동한 이후 왼쪽 공간은 모두 0로 채움, C/C++ 에 없음
  • Unary Operator(단일항)
    • ~(NOT, 비트 패턴 반전)
int a = 3 & 1;  // 0011 & 0001 = 1
int b = 2 | 1;  // 0010 | 0001 = 3
int c = 3 ^ 1;  // 0011 ^ 0001 = 2
int d = b >> 1; // 0011 에서 왼쪽으로 1칸 이동, 1(0001)
int e = b << 1; // 0011 에서 오른쪽으로 1칸 이동, 6(0110)
int f = ~a;     // 0001 -> 1111 1111 1111 1111 1111 1111 1111 1110
// 1000 0000 0000 0000 0000 0000 0000 0000
// ->
// 0100 0000 0000 0000 0000 0000 0000 0000
int g = -2147483648 >>> 1;

관계 연산자

  • Binary Operator(이항)
    • == : Equal to
    • != : Not equal to
    • > : greater than
    • < : less than
    • >= : greater than or equal to
    • <= : less than or equal to
  • primitive type 인 피연산자에서 연산 가능
  • 연산 결과 타입은 boolean

논리 연산자

  • Binary Operator(이항)
    • && (LOGICAL AND)
    • || (LOGICAL OR)
  • 피연산자의 타입은 boolean
  • 연산 결과 타입은 boolean

instanceof

  • Type introspection : 실행 시간에 객체의 타입이나 속성을 검사하는 프로그램의 능력을 뜻함

  • Java 에서 대표적인 type introspection

  • 객체의 타입을 비교할 때 사용

  • null 은 어떤 것의 instance 도 아님

class Test {
  ...
}

class Test2 extends Test{
  ...
}

class Operator{
    public static void main(String[] args) {
        Test obj1 = new Test();
        Test obj2 = new Test2();
        System.out.println(obj1 instanceof Test);    // true
        System.out.println(obj1 instanceof Test2);   // false
        System.out.println(obj2 instanceof Test);    // true, 상속 관계이기 때문?
        System.out.println(obj2 instanceof Test2);   // true
        System.out.println(null instanceof Object);  // false
    }
}

Assignment(=) operator

  • Binary Operator(이항)
    • = (ASSIGN)
    • += (ADD and ASSIGN)
    • -= (SUBTRACT and ASSIGN)
    • *= (MULTIPLY and ASSIGN)
    • /= (DIVIDE and ASSIGN)
    • %= (MODULO and ASSIGN)
    • &= (AND and ASSIGN)
    • ^= (XOR and ASSIGN)
    • |= (OR and ASSIGN)
    • <<= (LEFT SHIFT and ASSIGN)
    • >>= (RIGHT SHIFT and ASSIGN)
    • >>>= (UNSIGNED RIGHT SHIFT and ASSIGN)
  • 객체에 값을 할당
  • 다른 연산자와 묶어서 사용 가능
  • declaration statement, assignment expression 에서 사용됨
  • Java 는 reference type 의 경우 주소값을 할당한다는것에 주의해야 함

화살표(->) 연산자

  • 8 버전부터 람다 표현식(lambda expression) 이 공식적으로 적용되었음

  • 함수형 프로그래밍(Functional programming) 표현

    • side-effect 발생을 최소화 하기 위함
    • 조건
      • Pure function
      • Anonymous function
      • Higher-order function
    • Java 에서는 하나의 메소드가 선언된 인터페이스
  • 화살표 연산자는 Java 에서 람다 표현식의 syntax 일부

    (argument, ...) -> {expression}
interface Test{
    int func(int a);
}

class Test2 {
    public void func(Test test){
        int value = test.func(3);
        System.out.println(value);
    }
}

class Operator{
    public static void main(String[] args) {
        Test2 test2 = new Test2();
				// lambda expression 사용 X 버전
        test2.func(new Test() {
            public int func(int a){
                return a + 2;
            }
        });
				// lambda expression 사용 버전
        test2.func((a) ->{
            return a + 2;
        });
    }
}

3항 연산자

  • Conditional Operator

    • ?:

    • 구조

      Conditional Expression ? Expression(true인 경우) : Expression(false 인 경우);
  • 3항 연산자 사용 VS if-else 사용

    • 3항 연산자: expression
    • if-else: statement
    • 문법적인 의미로 보자면 3항 연산자는 expression 이므로 statement 내부 expression이 위치할 수 있는 모든 곳에서 사용 가능, expression 이므로 3항 연산자 자체를 중첩해서 사용 가능

 

int a = 2;
// if-else statement 사용
if(a == 2){
a += 1;
}
else{
a += 2;
}

// 3항 연산 사용
a == 2 ? a += 1 : a+=2 ;

연산자 우선 순위

기본적으로 연산자에는 우선순위가 있으며, 괄호의 우선순위가 제일 높고, 산술 > 비교 > 논리 > 대입의 순서이며, 단항 > 이항 > 삼항의 순서이다. 연산자의 연산 진행방향은 왼쪽에서 오른쪽으로 수행되며, 단항 연산자와 대입 연산자의 경우에는 오른쪽에서 왼쪽으로 수행된다. 

OperatorsPrecedence

postfix expr++ expr--
unary ++expr --expr +expr -expr ~ !
multiplicative * / %
additive + -
shift << >> >>>
relational < > <= >= instanceof
equality == !=
bitwise AND &
bitwise exclusive OR ^
bitwise inclusive OR |
logical AND &&
logical OR ||
ternary ? :
assignment = += -= *= /= %= &= ^= |= <<= >>= >>>=

 

Ref. https://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html

  • 동일 선상에 있는 연산자들은 동일한 우선 순위를 가짐
  • 할당 연산 제외한 Binary Operator 는 left ⇒ right 로 평가
  • 할당 연산은 right⇒ left 로 평가

(optional) Java 13. switch 연산자

switch(expression){
	case expression -> expression;
	...
	default -> expression
};

switch(expression){
	case expression:
		expression;
		yield expression;
	...
	default:
		expression;
		yield expression;
};
  • 차이점

    • case : 말고도 case -> 사용 가능
      • 화살표인 경우 branch fall-through 가 아님
      • 중괄호로 감싸야 하는 경우
        • multiple statement 를 적용
        • throw statement 사용, expression이 아닌 경우
    • break statement 대신 yield statement 사용
  • oracle 문서에서는 arrow case 라벨을 사용하는 것을 권장함

    • 이유:
      • colon case 라벨을 사용하면 헷갈릴 수 있음
      • 헷갈리게 되면 의도하지 않은 fall through 가 발생할 수 있음

 

반응형
반응형

홈브루는 루비 기반으로 만들어진 Mac OS X 용 패키지 관리자 입니다. 패키지 관리자는 맥에 설치되는 애플리케이션의 설치, 삭제, 업그레이드, 의존성 관리 등을 도와주는 도구로, 개발에 필요한 프로그램을 손쉽게 관리할 수 있게 해줍니다. 맥 개발자에게는 사실상 필수인 도구라고 할 수 있습니다.

Homebrew 설치하기

Homebrew는 Terminal 환경에서 곧바로 설치를 시작할 수 있다.

만약 Xcode가 설치되어 있지 않다면, Xcode를 설치하거나 Xcode command line tools가 미리 설치되어 있어야 한다.

#Xcode Command line tools 설치
xcode-select --install

Homebrew의 웹사이트를 확인해보면 설치 방법이 있다.

실제로 설치는 아래의 한줄만 Terminal에서 실행하면 끝납니다.

# Homebrew 설치하기 
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 
# 설치확인 
brew -v

Homebrew는 설치되는 모든 패키지를 /usr/local/ 디렉토리에 심볼릭 링크해서 관리하게 된다.

Homebrew 사용하기

Homebrew를 설치하게되면 터미널에서 brew 명령어를 사용해서 패키지를 관리 가능하다.

패키지 검색하기

Homebrew에서 패키지는 formula라고 부르며, Formulae라고 부느는 패키지 브라우저를 통해서 검색할 수 있다.

https://formulae.brew.sh/analytics/ 해당 주소로 접속하면 Homebrew를 통해 설치된 패키지의 목록과 통계를 볼 수 있다.

그 중, Install On Request Events 를 보면 사용자들이 어떠한 패키지를 가장 많이 설치하는지 알수 있다.

물론 brew search <formula> 명령어를 이용해서 패키지를 검색할 수도 있다.

# 패키지 검색하기 (rbenv, heroku) 
brew search rbenv 
brew search heroku

패키지 설치하기

패키지 설치는 brew install <formula> 명령을 이용한다.

brew install rbenv

패키지 업그레이드하기

brew outdated 명령어를 통해 업그레이드가 필요한 패키지의 목록을 조회할 수 있습니다. 만약 패키지를 최신 버전으로 업그레이드 하고싶다면 brew upgrade <formula> 명령을 이용합니다.

# 버전업된 패키지 확인하기 
brew outdated 
# 패키지 업그레이드 
brew upgrade rbenv 
# 모든 패키지 업그레이드하기 
brew upgrade

패키지 삭제하기

Homebrew는 패키지를 업그레이드 하더라도 예전버전의 패키지를 삭제하지 않기 때문에, 패키지를 설치하고 업그레이드 하다보면 오래된 버전의 패키지가 그대로 남아 있게 됩니다. 만약 이전 버전의 패키지가 필요없다면 brew cleanup <formula> 명령어를 이용해 최신버전의 패키지를 제외한 나머지를 모두 삭제할 수 있다.

# 최신버전의 rbenv 패키지만 남겨두기 
brew cleanup rbenv

만약 패키지 자체를 삭제하고 싶다면 아래와 같이 한다. brew uninstall <formula>

brew uninstall rbenv

패키지 관리하기

Mac에 설치된 패키지의 목록을 보기 위해서는 brew list 명령을 이용하며, 패키지의 정보를 확인 할 때는 brew info <formula> 명령을 사용한다.

# 설치한 패키지 목록보기 
brew list 
# 패키지의 정보 보기 
brew info rbenv

홈브루를 사용하다가 시스템 에러가 발생할 경우 doctor 명령으로 조회해 볼 수 있다.

# 시스템 오류 점검하기 
brew doctor

Homebrew 업데이트하기

홈브루 자체의 버전이 변경되었을 경우에는 brew update 명령을 통해서 Homebrew 자체를 최신버전으로 업데이트 할 수 있다..

brew update

Homebrew 삭제하기

Homebrew가 필요없어 졌다면 아래 스크립트를 통해 Homebrew를 삭제할 수 있습니다.

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall)"

홈브류 캐스크(cask)

홈브류에는 GUI 애플리케이션을 설치할 수 있는 캐스크 확장이 있다. 캐스크 패키지는 별도로 관리되며, 이 패키지를 설치하려면 brew 바로 뒤에 cask를 붙여준다. 예를 들어 홈브류 캐스크로 동영상 재생기 VLC를 설치하려면 다음 명령어를 실행한다.

brew cask install vlc

 

참고문헌

brew.sh/index_ko[공식문서]
formulae.brew.sh/analytics/ [홈브루 많이 쓰는 목록] 

 

반응형
반응형

목표

자바의 프리미티브 타입, 변수 그리고 배열을 사용하는 방법을 익힙니다.

학습할 것

  • 프리미티브 타입 종류와 값의 범위 그리고 기본 값
  • 프리미티브 타입과 레퍼런스 타입
  • 리터럴
  • 변수 선언 및 초기화하는 방법
  • 변수의 스코프와 라이프타임
  • 타입 변환, 캐스팅 그리고 타입 프로모션
  • 1차 및 2차 배열 선언하기
  • 타입 추론, var

 

프리미티브 타입 종류와 값의 범위 그리고 기본 값

 

 

타입

 할당되는 메모리 크기

 기본값

 데이터의 표현 범위

 

 논리형

 boolean

 1 byte

 false

 true, false

 정수형

 byte

 1 byte

 0

 -128 ~ 127

 short

 2 byte

 0

 -32,768 ~ 32,767

 int(기본)

 4 byte 

 0

 -2,147,483,648 ~ 2,147,483,647
-2^{31} ~ 2^{31}-

 long

 8 byte

 0L

 -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807

 실수형

 float

 4 byte

 0.0F

 (3.4 X 10-38) ~ (3.4 X 1038) 의 근사값

 double(기본)

 8 byte

 0.0  (1.7 X 10-308) ~ (1.7 X 10308) 의 근사값

 문자형

 char

 2 byte (유니코드)

 '\u0000' 

 0 ~ 65,535

 

자바 8부터 

unsigned int 및

unsigned long 이라는 개념이 추가됨.

 

1byte 는 8bit 이다. 1bit 가 추가 될때마다 표현가능한 숫자가 2배가 된다.

부호가 있는 자료형의 경우 1비트는 부호츨 표현하기 위해 사용하기 떄문에 1byte 의 경우 -128 ~ 127 까지 표현 가능하다.

양수는 0이 포함되기 떄문에 128이 아니다.

만약 0 ~ 255 까지 표현하고 싶다면, 부호 비트 자리도 데이터로 취급하려면 unsigned 자료형을 사용하면 된다. 음수는 표현하지 못하는 대신 양수 표현 범위가 두 배 늘어난다.

2비트로 표현 가능했던 모든 값 : 00, 01, 10, 11

 

자바에는 unsigned 라는 자료형은 제공하지 않고,

Integer.toUnsignedString() 메소드 등으로 제공한다. 

 

실수형의 경우 정수형과 비교했을 떄 메모리 크기는 비슷한데 값의 표현 범위가 훨씬 넓다.

 

실수는 부호(sign), 가수(Mantissa), 지수(exponent) 로 구성되며 부동 소수점 방식을 사용한다.

부동 소수점 방식을 사용하여 모든 기수를 0보다 크거나 같고 1보다 작은 값 범위의 값으로 만들고 원래 수를 표현하기 위해 10을 몇번 거듭 제곱해야 하는지 지수로 표현한다.

sign: 부호를 나타내기 위해 사용하는 비트

exponent: 지수를 사용하기 위해 사용하는 비트

Mantissa: 가수를 사용하기 위해 사용하는 비트

실수 표현 예제

-118.625를 IEEE 754(32비트 단정밀도)로 표현해 보겠습니다.

  1. 우선 음수이므로 부호비트는 1이 됩니다.
  2. 부호를 뺀 절대값을 이진법으로 나타내면 1110110.101(2)이 됩니다.
  3. 소수점을 왼쪽으로 이동시켜 왼쪽에는 1만 남도록 만듭니다. 1110110.101 = 1.110110101 * 2^6 으로 만듭니다. 이것을 정규화된 부동소수점 수라고 합니다.
  4. 가수부는 소수점의 오른쪽 부분으로, 부족한 비트 수 부분만큼 0으로 채워 23비트로 만듭니다.
  5. 지수는 6이며 Bias를 더해야 합니다. 32비트 IEEE754형식에서 Bias는 127이므로 133이되고 이를 이진법으로 변환하면 10000101이 됩니다.

java에서 기본적으로 실수리터럴을 사용하면 double 형식입니다.

그렇기 때문에 float형식의 실수는 마지막에 f를 붙여 float형식의 실수라고 알려주어야 한다. 하지만 float형식은 현재 사용하지 않는 것을 권장한다. 부동 소수점 형식은 정확한 실수값이 아닌 근사값을 저장하는 방식이기 때문에 32비트인 float는 오차가 생길 확률이 크다.

 

프리미티브 타입과 레퍼런스 타입

Java Data Type
ㄴ Primitive Type
    ㄴ Boolean Type(boolean)
    ㄴ Numeric Type
        ㄴ Integral Type
            ㄴ Integer Type(short, int, long)
            ㄴ Floating Point Type(float, double)
        ㄴ Character Type(char)
ㄴ Reference Type
    ㄴ Annotation
    ㄴ Array
    ㄴ String
    ㄴ Class
    ㄴ Enumeration
    ㄴ Interface
Primitive Type Reference Type
boolean, char, byte, short, int등 이미 정해진 유형 사용자가 무제한적으로 유형을 선언
값 저장 주소 저장
call by value call by reference
메모리에 저장되는 값이 실제값 저장되어 있는 값은 메모리의 주소
동일한 유형의 다른 변수에 값이 복사됨 다른 참조유형에 할당되면 동일한 객체를 가리킴
메소드에 전달되면 사본만 전달됨. 메서드에서는 Primitive Type의 원본에 접근할 수 없음. 메서드는 복사된 값을 변경 가능 객체가 메소드에 전단되면 메소드는 주소값을 전달받게되어 객체의 내용을 변경할 수 있음. 객체의 주소는 변경불가

위의 값들은 JVM 의 Runtime Data Area 에 저장된다. 

String name ="james";   // name 변수 와 주소값은 스택에, 실제값은 힙 영역에 생성
int age = 20; // age 변수 와 값은 스택영역에 생성
Person person = new Person(name, age);
stack Heap
name james  
age 20  
person   (주소값)---------------> Person

 

리터럴

리터럴은 실제값 그 자체입니다. 소스코드에서 고정된 값을 대표하는 용어이며 리터럴은 변수 초기화에 사용됩니다.

  • Integer Literals
    • long 타입은 L 로 끝나거나 l 로 끝나는 값
    • 그외 나머지 숫자는 int
    • 16진수: 0x 로 시작
    • 2진수: 0b 로 시작
  • Floating-Point Literals
    • float 타입은 F로 끝나거나 f 로 끝나는 값
    • 그 외 나머지는 double (optional, D 혹은 d 로 끝나는 값)
  • Character and String Literals
    • Unicode character
    • special escape character
      • \b : 백스페이스
      • \t : 탭
      • \n : new line
      • \f : form feed
      • \r : 캐리지 리턴
      • \" : 쌍따옴표
      • \' : 따옴표
      • \\ : 역슬래시

 

 

변수 선언 및 초기화하는 방법

선언 - Declaration?

변수를 선언한다는 것은, 저장공간을 확보하겠다는 의미로 해석할 수 있다.

int a;

위의 코드가 변수를 선언한 것인데, 해석하자면 다음과 같다.
int 타입의 값을 저장할 수 있는 공간을 확보했고(int 타입은 4byte) 그 공간을 지칭할 이름은 a 이다.

초기화 - Initialization?

변수를 초기화 한다는 것은, 저장공간에 원하는 값을 저장하는 것을 의미한다.
변수를 선언하고 나면, 해당 공간에는 아무런 의미 없는 쓰레기값이 들어가있게 된다. 그리고 그 상태에서 컴파일을 시도하면
Error:(10, 28) java: variable a might not have been initialized 와 같은 컴파일 에러코드를 볼 수 있을 것이다.
그러므로 변수는 선언 후에 초기화를 해야하며 위에 선언한 변수에 대한 초기화는 다음과 같이 할 수 있다

a = 10;

선언과 초기화

변수의 선언과 초기화를 한 줄에 하는 것도 가능하다.

int a = 10;

 

초기화 블록

클래스 초기화 블럭 : 클래스 변수의 복잡한 초기화에 사용된다. 클래스가 처음 로딩될 때 한번만 수행된다.

  - class 로딩시에 호출된다.

  - 인스턴스 변수나 인스턴스 메소드에 접근 못함. 

 

인스턴스 초기화 블럭 : 인스턴스 변수의 복잡한 초기화에 사용된다. 

  - 객체 생성할때마다 호출됨.

  - super 생성자 이후에 실행됨.

  - 생성자 보다 먼저 실행됨.

  - 모든 생성자의 공통 코드를 instance initializer block 에 넣으면 코드 줄일수 있다.

 

class InitBlock{
    static {
        /* 클래스 초기화 블럭 */
    }

    {   /* 인스턴스 초기화 블럭 */ }
} 

 

변수의 스코프와 라이프타임

클래스 변수는 static을 앞에 붙여서 선언해주어야 한다.

지역변수는 메소드 안에서 선언을 하면 지역변수로 된다.

인스턴스 변수는 클래스 내부에 생성된 변수이다.

public class scope_and_lifetime {
    int num1, num2;   		//Instance Variables
    static int result;  	//Class Variable
    int add(int a, int b){  	//Local Variables
        num1 = a;
        num2 = b;
        return a+b;
    }
}
클래스 변수(스태틱 변수) 클래스 영역 클래스가 메모리에 올라갈 때 클래스 전역(클래스 기반으로 생성된 각각의 인스턴스에 공유됨)
인스턴스 변수 클래스 영역 인스턴스가 생성될 때 각각의 인스턴스
지역 변수 메소드 영역 변수 선언문이 수행되었을 때 메소드 안

각각의 변수의 라이프타임은 클래스 변수의 경우 프로그램이 종료할때까지 적용되고 인스턴스 변수의 경우는 인스턴스가 참조 되고 있을때에는 유지되다가 객체를 참조하는 변수가 없을 경우 JVM의 Garbage Collector가 제거하게 된다.

지역변수의 경우 메소드가 끝나면 소멸되어 사용할 수 없게 됩니다.

인스턴스변수는 클래스가 로딩될떄 생성되서, 스태틱 함수에서는 인스턴스 변수 사용 불가
스태틱 변수에도 인스턴스메소드 사용 불가
인스턴스변수에는 반대로 스태틱 변수 참조가능 왜냐하면 스태틱변수가 먼저 생성되기 때문이다.

타입 변환, 캐스팅 그리고 타입 프로모션

타입 변환으로 종류로는 캐스팅(강제 형변환)과 타입 프로모션이 있습니다(자동 형변환).

타입캐스팅이란 크기가 더 큰 자료형을 크기가 더 작은 자료형에 대입하는 것을 의미.

데이터가 작은데서 큰 곳으로 옮기는 타입 프로모션의 경우 오류나 문법의 필요없이 형변환이 가능하지만,

반대로 타입캐스팅은 데이터 표현범위가 작은 곳으로 옮길 경우 표현범위를 넘어나게 되면 전혀 다른 값이 나올수도 있다.

 

타입 캐스팅

// 큰 범위에서 작은범위로 캐스팅
int a = 10;     
byte b = (byte)a;
System.out.println(b); //  -> 10
(byte 는 -256~255까지 표현할 수 있음으로 타입캐스팅을 했음에도 데이터 변형이나 
손실은 오지 않았다) 

// 작은 범위에서 큰 범위로 캐스팅	
int a = 10000;     
byte b = (byte)a;
System.out.println(b); //  -> 16
(표현범위를 벗어나는 값을 강제로 타입캐스팅해 데이터에 변형이 생겼다) 

 

타입 프로모션

byte a = 10;
int b = a;
System.out.println(b); //  -> 10

타입변환은 레퍼런스 타입에서도 가능하다.

 

부모클래스로의 타입변환은 자동적으로 가능하지만 자식클래스로의 타입변환은 타입캐스팅이 필요하다.

이유는 자식클래스는 부모클래스의 필드나 메소드를 물려받음으로 자식클래스타입의 객체를 부모클래스타입으로 바꾼다고 해서 데이터의 손실이나 변형이 일어나진 않기 때문이다.

  • Inheritance 관계에서만 가능
  • Upcast : subclass → superclass
    • 모든 subclass 는 superclass 의 컨텐츠를 가지고 있으므로 superclass 로의 casting 이 가능함
  • Downcast: superclass → subclass
    • 모든 superclass 는 subclass 의 컨텐츠를 가지고 있지 않을 수도 있음, 그러므로 오류 발생 가능성 ↑

 

1차 및 2차 배열 선언하기

class ArrayExample {
	public static void main(String[] args) {
        //1차원 배열
        int[] oneDimensionArrayEx1 = {1, 2, 3, 4, 5};
        int[] oneDimensionArrayEx2;
        oneDimensionArrayEx2 = new int[10];

        //2차원 배열
        int[][] twoDimensionArrayEx1 = {{1, 2}, {3, 4}};
        int[][] twoDimensionArrayEx2;
        twoDimensionArrayEx2 = new int[10][10];
    }
}

 

  • oneDimensionArrayEx1 은 Runtime Stack 영역의 힙 영역 주소값을 가짐
  • Heap 영역에 int 타입 크기의 요소 5개를 할당하여 사용됨

 

  • 2차원 배열

  • Runtime Stack 영역의 twoDimensionArrayEx1 은 2개의 요소 크기(2개 요소에 주소값을 가지고 있음)를 가진 힙 영역 주소값을 가짐
  • 힙 영역에는 실제 값이 들어있는 요소들과 주소값이 들어있는 요소들로 존재하게됨

 

타입 추론, var

Java 10부터 추가된 특징중 하나인 Local Variable Type Inference은 로컬 변수 선언을 var를 이용하여 기존의 엄격한 타입 선언방식에서 컴파일러에게 타입추론 책임을 위임할 수 있게 되었다.

var list = new ArrayList<String>(); //infers ArrayList<String> 
var stream = list.stream();//infers Stream<String>

 

Local Variable Type Inference 사용 조건

• 초기화된 로컬 변수 선언시

• 반복문에서 지역변수 선언 시(enhanced for loop포함)

var 활용

1. 지역변수 선언

var numbers = Arrays.asList(1, 2, 3, 4, 5); 
for (var i = 0; i < numbers.size(); i++) { 
	System.out.println("numbers = " + numbers.get(i)); 
}

2. forEach

var numbers = Arrays.asList(1, 2, 3, 4, 5); 
for (var number : numbers) { 
	System.out.println(number); 
}

 

⇒ 기존에는 Object타입으로 받아서 형변환을 하거나 IDE가 아닌 개발자가 직접 타입추론해 명시적 타입선언을 해줬는데 var를 사용하여 훨씬 편하게 타입선언이 가능해진다.

3. Lambda (Java 11)

IntBinaryOperator plus10 = (@NonNull var one, @NonNull var two) -> one + two + 10;

 

⇒ Java 11부터는 람다 인자에도 var사용이 가능해졌는데, 이를 통해 파라미터 어노테이션 사용까지 가능해졌다.

반응형
반응형
public int[] solution(int[] prices) {
	int len = prices.length; // 5
	int[] answer = new int[len];
	int i, j;
	for (i = 0; i < len; i++) {
		for (j = i + 1; j < len; j++) {
			answer[i]++;
			if (prices[i] > prices[j])
				break;
		}
	}
	return answer;
}

문제 설명

초 단위로 기록된 주식가격이 담긴 배열 prices가 매개변수로 주어질 때, 가격이 떨어지지 않은 기간은 몇 초인지를 return 하도록 solution 함수를 완성하세요.

제한사항

  • prices의 각 가격은 1 이상 10,000 이하인 자연수입니다.
  • prices의 길이는 2 이상 100,000 이하입니다.

입출력 예

pricesreturn

[1, 2, 3, 2, 3] [4, 3, 1, 1, 0]

입출력 예 설명

  • 1초 시점의 ₩1은 끝까지 가격이 떨어지지 않았습니다.
  • 2초 시점의 ₩2은 끝까지 가격이 떨어지지 않았습니다.
  • 3초 시점의 ₩3은 1초뒤에 가격이 떨어집니다. 따라서 1초간 가격이 떨어지지 않은 것으로 봅니다.
  • 4초 시점의 ₩2은 1초간 가격이 떨어지지 않았습니다.
  • 5초 시점의 ₩3은 0초간 가격이 떨어지지 않았습니다.

문제 추가 설명. 

첫 번째 배열값 1이 다음 배열값을 순환하면서 값이 커질떄까지의 값을 구한다.

첫번째 1은 4번 반복동안 더 작은값이 없음.

세번째 배열 3은 바로 다음 배열값 2가 작으므로 1초라는 값 가짐.

네번째는 배열값 2는 다음 배열까지 작아지는 값 없으므로 1초

다섯번째 배열값은 마지막이므로 0초

 

 

반응형
반응형

1. java.lang.UnsupportedClassVersionError 발생 원인 

 

Unsupported major.minor version 52.0

 

Java SE 15 = 59 (0x3B hex),
Java SE 14 = 58 (0x3A hex),
Java SE 13 = 57 (0x39 hex),
Java SE 12 = 56 (0x38 hex),
Java SE 11 = 55 (0x37 hex),
Java SE 10 = 54 (0x36 hex),
Java SE 9 = 53 (0x35 hex),
Java SE 8 = 52 (0x34 hex),
Java SE 7 = 51 (0x33 hex),
Java SE 6.0 = 50 (0x32 hex),
Java SE 5.0 = 49 (0x31 hex),
JDK 1.4 = 48 (0x30 hex),
JDK 1.3 = 47 (0x2F hex),
JDK 1.2 = 46 (0x2E hex),
JDK 1.1 = 45 (0x2D hex).

 

 

 


java.lang.UnsupportedClassVersionError는 높은 버전의 JDK에서 컴파일한 class 파일을 낮은 버전의 JDK에서 실행을 해서 발생하는 에러다.

 

위 에러가 없으려면 실행환경과 컴파일할 자바버젼을 맞춰줘야 한다.

컴파일시 자바버젼을 맞추기위해서는 jacac 에 -target 옵션을 줘야 한다.

javac -target 1.2 Helloworld.java

 

반응형
반응형

문제 설명

수많은 마라톤 선수들이 마라톤에 참여하였습니다. 단 한 명의 선수를 제외하고는 모든 선수가 마라톤을 완주하였습니다.

마라톤에 참여한 선수들의 이름이 담긴 배열 participant와 완주한 선수들의 이름이 담긴 배열 completion이 주어질 때, 완주하지 못한 선수의 이름을 return 하도록 solution 함수를 작성해주세요.

제한사항

  • 마라톤 경기에 참여한 선수의 수는 1명 이상 100,000명 이하입니다.
  • completion의 길이는 participant의 길이보다 1 작습니다.
  • 참가자의 이름은 1개 이상 20개 이하의 알파벳 소문자로 이루어져 있습니다.
  • 참가자 중에는 동명이인이 있을 수 있습니다.

입출력 예

participant                                                   completion                                                  return

[leo, kiki, eden] [eden, kiki] leo
[marina, josipa, nikola, vinko, filipa] [josipa, filipa, marina, nikola] vinko
[mislav, stanko, mislav, ana] [stanko, ana, mislav] mislav

입출력 예 설명

예제 #1
leo는 참여자 명단에는 있지만, 완주자 명단에는 없기 때문에 완주하지 못했습니다.

예제 #2
vinko는 참여자 명단에는 있지만, 완주자 명단에는 없기 때문에 완주하지 못했습니다.

예제 #3
mislav는 참여자 명단에는 두 명이 있지만, 완주자 명단에는 한 명밖에 없기 때문에 한명은 완주하지 못했습니다.

 

정답

import java.util.HashMap;

class Solution {
    public String solution(String[] participant, String[] completion) {
        String answer = "";
        HashMap<String, Integer> map = new HashMap<>();
        for (String player:participant) {
          map.put(player,map.getOrDefault(player,0)+1);
        }
        for (String player:completion){
          map.put(player,map.get(player)-1);
        }

        for(String key : map.keySet()){
          if(map.get(key) !=0){
            answer = key;
          }
        }
        return answer;
    }
}

map 은 중복을 허용하지 않는 자료구조 이므로 for 문으로 map 에 1차적으로 넣고, 다음 for 문으로 기존에 있었는지에 대해 검사를 해야한다.

반응형
반응형

JVM은 자바 가상머신으로 자바 바이트코드를 실행 할 수 있는 주체로 JVM 덕분에 CPU나 운영체제(플랫폼)과 독릭접으로 동작 가능하다.


JVM은 크게 Class Loader,GC, Runtime Data Area, Excute engine 세가지로 나뉜다

JVM 구성요소

1. Class Loader

컴파일된 자바 바이트코드Runtime Data Area 영엑에 로드한다.

자바 컴파일러가 ,java 파일을 컴파일하면 .class 파일 을 만드는데, 이게 바로 바이트코드이고 이걸 데이터영역에 로드하는 것이다.

 

javac 가 바이트코드로 컴파일을 하게 되는데 이건 jdk 에 있는 기능이다. JRE 는 실행환경이기 때문에 컴파일 기능이 없다.

자바 9 이후 부터는 JRE 가 따로 제공되지 않는다.

 

2. Excute engine

Class Loader 를 통해 JVM 내의 Runtime Data Area 에 배치된 바이트코드를 실행한다.

실행엔진으로는

명령어를 하나 하나 실행하는 인터프리터 방식과 

실행 시점에 자주 쓸만한 코드들을 기계어로 변환 시켜놓고 저장해서 사용하는 JIT 방식이 있다.

다시 말하면 JIT 컴파일러는 자주 사용되는 코드일 경우에만 기계어로 캐싱하고 그 부분이 호출이 되면 실행이 된다.

 

여기 실행엔진에 GC 를 넣는 사람이 있고, 실행엔진과 별개로 JVM 의 큰 범주로 나누는 사람이 있다.

GC 란 Heap 메모리 영역에 생성 된 객체들 중 사용하지 않는 객체를 탐색 후 제거하는 역할을 하는 것이다.

 

 

여기서 런타임 데이터영역은 또 여러가지 구조로 나뉜다.

 

3. Runtime Data Area

JVM의 메모리 영역으로 자바 애플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역이다.

이 영역은 크게 Method Area, Heap Area, Stack Area, PC Register, Native Method Stack로 나눌 수 있다.

 

1. Method area (메소드 영역)

클래스 멤버 변수의 이름, 데이터 타입, 접근 제어자 정보같은 필드 정보와 메소드의 이름, 리턴 타입, 파라미터, 접근 제어자 정보같은 메소드 정보, Type정보(Interface인지 class인지), Constant Pool(상수 풀 : 문자 상수, 타입, 필드, 객체 참조가 저장됨), static 변수, final class 변수등이 생성되는 영역이다.

 

2. Heap area (힙 영역)

new 키워드로 생성된 객체와 배열이 생성되는 영역이다.

메소드 영역에 로드된 클래스만 생성이 가능하고 Garbage Collector가 참조되지 않는 메모리를 확인하고 제거하는 영역이다.

 

3. Stack area (스택 영역)

지역 변수, 파라미터, 리턴 값, 연산에 사용되는 임시 값등이 생성되는 영역이다.

동적으로 객체를 생성하면 실제 객체는 Heap에 할당되고 해당 레퍼런스만 Stack에 저장된다. Stack은 스레드별로 독자적으로 가진다.

int a = 10; 이라는 소스를 작성했다면 정수값이 할당될 수 있는 메모리공간을 a라고 잡아두고 그 메모리 영역에 값이 10이 들어간다. 즉, 스택에 메모리에 이름이 a라고 붙여주고 값이 10인 메모리 공간을 만든다.

클래스 Person p = new Person(); 이라는 소스를 작성했다면 Person p는 스택 영역에 생성되고 new로 생성된 Person 클래스의 인스턴스는 힙 영역에 생성된다.

그리고 스택영역에 생성된 p의 값으로 힙 영역의 주소값을 가지고 있다. 즉, 스택 영역에 생성된 p가 힙 영역에 생성된 객체를 가리키고(참조하고) 있는 것이다.

메소드를 호출할 때마다 개별적으로 스택이 생성된다.

Heap에 있는 오브젝트가 Stack에서 참조 할 수 없는 경우 GC의 대상이 된다.

 

4. PC Register (PC 레지스터)

Thread(쓰레드)가 생성될 때마다 생성되는 영역으로 Program Counter 즉, 현재 쓰레드가 실행되는 부분의 주소와 명령을 저장하고 있는 영역이다. (*CPU의 레지스터와 다름)

이것을 이용해서 쓰레드를 돌아가면서 수행할 수 있게 한다.

 

5. Native method stack

자바 외 언어로 작성된 네이티브 코드를 위한 메모리 영역이다.

보통 C/C++등의 코드를 수행하기 위한 스택이다. (JNI)

 

쓰레드가 생성되었을 때 기준으로

1,2번인 메소드 영역과 힙 영역을 모든 쓰레드가 공유하고,

3,4,5번인 스택 영역과 PC 레지스터, Native method stack은 각각의 쓰레드마다 생성되고 공유되지 않는다.

 

 

JIT 컴파일러란(Just-In-Time)

JRE안에 존재하고, 

사용하는 이유는 같은 코드를 매번 해석하지 않고 실행할 때 컴파일을 하면서 해당코드를 캐싱한다.

이후엔 바뀐 부분만 컴파일 하고 나머지는 캐싱된 코드를 사용해서 인터프리터의 속도를 개선하는 역할을 한다.

 

JDK와 JRE의 차이

  • JDK = JRE + @ 이며

  • JRE는 읽기 전용, JDK 읽기 / 쓰기 전용이라 생각할 수 있다.

JRE(Java Runtime Enviroment) : 컴파일된 자바 프로그램을 실행시킬 수 있는 자바 환경

JDK(Java Development kit) : 자바 프로그래밍시 필요한 컴파일러 등 포함

 

Runtime Data Area 및 JIT 컴파일러에 대해서는 따로 포스팅 할 예정이다.

 

반응형
반응형

# free -m
                       total        used        free      shared  buff/cache   available
Mem:         257751        1842      254508         105        1400      255327
Swap:          4095           0        4095

1. 리눅스 가용 메모리 확인하기
total - 전체 물리적인 메모리의 크기
used - 사용중인 메모리 크기
free - 사용중이 아닌 메모리 크기로 사용 가능한 메모리 크기
shared - 공유 메모리 크기
buff/cache - 버퍼/페이지로 사용되고 있는 메모리 크기
available  -  실직적으로 사용 가능한 메모리, free 필드값의 메모리가 부족시 해제되는 커널내 메모리 영역 사이즈를 합친 값

2. free 옵션
-m            // 메가 바이트 단위
-g            // 기가 바이트 단위
-k           // 킬로 바이트 단위
-l           // 최고/최저 메로리 상황을 구분하여 출력

-h         // 기가 바이트로 변환 및 소수점 까지 표시

반응형

+ Recent posts