티스토리 뷰
Primitive Type 종류와 값의 범위 그리고 기본 값
Primitive Variable 이란?
어떠한 Instance의 참조 값을 가지지 않고, 지정된 Type에 맞는 리터럴을 저장한 변수를 말한다.
객체를 다루지 않기 때문에 Null을 저장할 수 없으며, 같은 타입의 변수들이 동일한 값을 다룰 때에는 Operand Stack이나 Constant Pool에 리터럴을 저장해두었다가 꺼내어 사용한다.
**// 정수 타입
// JDK 7 까지는 int와 long에 대해서 Unsigned 를 지원하지 않았지만,
// JDK 8 부터는 int와 long에 대하여서 지원하기 시작하였다.**
// 1 byte (8 bit)
// -128 (-2^7) ~ 127 (2^7–1).
// 기본 값은 0. (공통적으로 Method, Loop Scope 등에 선언된 Primitive 변수는 초기화 해야한다.)
byte variableB;
// 2 byte (16 bit)
// -32,768(-2^15) ~ 32,767(2^15–1).
// 기본 값은 0.
short variableS;
// 4 byte (32 bit)
// 2,147,483,648 (-2^31) ~ 2,147,483,647 (2^31-1)\
// int 를 통해 8, 16 진수를 표현 가능하다. 0 시작하면 8진수, 0x 로 시작하면 16진수 이다.
// (JDK 8+) 부호 없는 int를 만들기 위해서는 Integer.parseUnsignedInt 를 사용해야 한다.
// 기본 값은 0.
int variableI;
// 8 byte (64 bit)
// -9,223,372,036,854,775,808 (-2^63) ~ 9,223,372,036,854,775,807 (2^63–1)
// (JDK 8+) 부호 없는 long를 만들기 위해서는 Long.parseUnsignedLong 를 사용해야 한다.
// 기본 값은 0.
long variableL;
**// 실수 (부동소수점 방식) 타입**
// 4 byte (32 bit)
// 1.40239846 x 10^-45 ~ 3.40282347 x 10^38
// 기본 값은 0.0f
float variableF;
// 8 byte (64 bit)
// 4.9406564584124654 x 10-324 ~ 1.7976931348623157 x 10308
// 기본 값은 0.0D
double variableD;
**// 논리 타입**
// 표시 용량은 1 bit (내부적으로는 1 byte 내부 7 비트에 값을 채우고 하나의 bit 만 사용한다.)
// true , false
// 기본 값은 false
boolean bool;
**// 문자 타입**
// 2 Byte (16 bit)
// 유니코드를 표현하는 변수이며, 값의 범위는 0 ~ 65,535 까지이다.
// 기본 값은 /u0000 (Unicode Character 'NULL')
char variableC
Primitive Type과 Reference Type
Reference Type?
Reference Type 은 Primitive Type을 제외한 모든 타입을 포함한다.
참조 값을 통해 관리하기 때문에 Reference Type이라고 한다. ( Null을 사용할 수 있다. )
Wrapper Class?
Primitive Type을 인스턴스로 다룰 수 있게끔 도와주는 것들을 말한다.
값을 조작하기 위해 작성된 Util Method를 사용하기 위해서 이용하는 경우도 많다.
- Min, Max_value 상수, valueOf, parsexxx, toString 등..
Boxing과 Unboxing을 통해 Primitive Type을 감싸거나 다시 Primitive로 변환할 수 있다.
//대응 클래스
byte Byte char Character
short Short float Float
int Integer double Double
long Long boolean Boolean
//Wrapper Class 선언 예시
Integer num = new Integer(10);
= Integer.valueOf(10);//혹은 primitive 변수
// Integer의 valueOf 메서드는 Boxing 할 값이-127~128 범위 값인 경우 기존에 있는 객체를
// 재사용할 수 있게끔 작성되어 있다.
// IntegerCache 클래스에 -127~128 만큼의 범위를 가지는 별도의 배열을 만들고
// 해당 valueOf 로직에서 검증하여 중복된 경우 기존에 선언된 객체를 반환한다.
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
Primitive Type과 Reference Type의 차이점?
-
Reference 변수를 통해서 생성된 객체에 접근하고 조작하고 값을 받아올 수 있다.
-
Null을 다룰 수 있다. (NPE 가 발생될 수 있다.)
- Null 을 가지는 Wrapper와 Primitive Type 연산 시 NPE 가 발생한다.
-
Generic을 사용할 수 있다.
-
별도의 식별 값을 가진다. (Hashcode)
-
성능 상의 차이가 있을 수도 있다.
-
Boxing과 UnBoxing의 오버헤드
-
Heap 영역에서의 생성 후 참조 값의 연결 과정. (Constant Pool 과의 참조도 있을 수 있다.)
-
그러면 Wrapper Class 를 사용하지 말라는 걸까?
- Front 단의 데이터를 검증해야 한다거나, DB Table에서 Null을 다루고 있다면, 해당 데이터를 받아오는 객체에서 검증을 진행해야 하는 것이 맞다.
- DB Table에서 Null 을 다룰 때 변수를 Primitive로 선언하여 사용한다면 0이 저장될 것이고 의도치 않은 결과가 발생할 수 있다고 생각한다.
- Collection이나 Generic 은 Primitive를 지원하지 않는다. (결국 Wrapper를 사용해야 한다.)
리터럴
리터럴이란? wiki
어떤 변수에 의해 저장되는, 값 자체로써 변화하지 않는 것들을 의미한다.
// 변수를 초기화할 때 사용되는 값들도 모두 리터럴이다.
int numberA = 10;
double numberB = 10.11D;
String str = "문자열 리터럴";
변수 선언 및 초기화하는 방법
흐름
- 타입에 맞는 메모리 공간을 확보하고 (byte b;)
- 타입에 맞는 리터럴을 저장한다. (byte b = 100;)
// 정수 리터럴의 _ 은 숫자를 구별하기 위해 사용할 수 있게 지원해준다.
// 100_000 = 100,000
// 맨 앞이나 뒤에 _ 를 작성할 경우 컴파일 에러가 발생한다.
byte variableB;
variableB = 100;
short variableS;
variableS = 30_000;
// 10진수
int variableI = 100_000;
// 8진수
int variableI = 010; // 8
// 16진수
int variableI = 0xa; // 10
// 2진수
int variableI = 0b11; // 3
long variableL = 100_000_000_000; // 혹은 100_000_000_000l;
float variableF = 3.14f;
double variableD = 3.14; // 3.14D; 기본적으로 Double 로 판단하여 선언해준다.
char variableC = 'c';
boolean bool = true;
Variable Scope와 Life Cycle?
Class Scope
public class someClass {
// 해당 Class 의 Bracket 내부에서만 사용이 가능하다.
// 외부에서는 해당 Class 의 getter, setter 를 통해서 해당 변수를 접근할 수 있다.
private int age = 32;
-------------------------------------------
}
Method Scope
public class someClass {
public static void main(String[] args) {
VariableScope variableScope = new VariableScope();
variableScope.someMethodA();
System.out.println(variableScope.someMethodB());
}
public void someMethodA() {
// 해당 Method 의 Bracket 내부에서만 사용이 가능하다.
int count = 0;
System.out.println("count = " + count);
}
public int someMethodB() {
//Compile Error 발생
//cannot find symbol
//symbol: variable count
//location: class noteThree.VariableScope
count += 1;
return count;
}
}
Loop Scope
public class someClass {
public static void main(String[] args) {
VariableScope variableScope = new VariableScope();
variableScope.min(new int[]{10,20,30,40,50});
}
public void min(int[] args) {
int min = 21700000;
for (int arg : args) {
// int arg 는 해당 Loop 내부에서만 사용이 가능하다.
if (min > arg) { min = arg; }
System.out.println("arg = " + arg);
}
//cannot find symbol.. symbol: variable arg...
System.out.println("arg = " + arg);
System.out.println("min = " + min);
}
}
Bracket Scope
public class someClass {
public static void main(String[] args) {
VariableScope variableScope = new VariableScope();
variableScope.someMethod();
}
public void someMethod() {
int numberA = 0;
{
// 해당 변수는 자신을 감싸는 Bracket 영역에서만 사용 가능하다.
int numberB = 1;
numberA += numberB;
}
//cannot find symbol.. symbol: variable arg...
System.out.println(numberB);
System.out.println("numberA = " + numberA); // 1
}
}
Variable Shadowing
public class someClass {
public static void main(String[] args) {
VariableScope variableScope = new VariableScope();
variableScope.someMethodA();
variableScope.someMethodB();
}
//Class Scope Variable
private int count = 10;
public void someMethodA(){
// Instance Variable 인 count 를 접근하여 사용한다.
System.out.println("count = " + count);
}
// Class Scope > Method Scope
public void someMethodB(){
// Method 내부에 Instance Variable 인 count와 동일한 이름을 가진 변수가 존재한다.
// 동일한 이름의 변수가 하위 Scope에서 존재한다면 하위 Scope의 변수가 상위 Scope의
// 변수를 가리게(Shadowing) 된다.
int count = 1;
System.out.println("count = " + count);
}
}
Variable Life Cycle
-
Static Variable (Class Member Variable)
static 키워드가 붙은 필드 변수를 말하며, 전역적으로 접근이 가능한 녀석이다.
인스턴스 생성 이전에 미리 로드되어 생성되고 Heap 영역에서 관리된다. (JDK 8+)
더 이상 해당 Class (Static Obejct)가 참조되지 않는 경우 GC 된다.
(JDK 7 이전에선 Application 의 Life Cycle이 종료될 때까지 유지된다.)
-
Instance Member
class scope 에서 작성된 변수를 말한다. 인스턴스의 참조 값을 통해서 접근과 조작이 가능하다.
인스턴스 생성시에 메모리 공간을 가지고 기본 값으로 초기화되거나 생성자를 통해 주입된다.
더 이상 해당 Instance가 참조되지 않는 경우 GC 된다.
-
Local Variable
Method, Loop Scope 등에서 생성되어 사용되는 지역 변수들을 말한다.
지역 변수가 포함된 Scope가 값을 반환하는 등, 로직이 끝난다면 사라진다.
Type Conversions, Casting, Type Promotion
Type Conversions
-
Widening Conversion
Type 간의 호환성이 존재하고 변환될 타입이 이전에 지니고 있던 타입보다 큰 경우 자동으로 변환되는 것을 말한다.
(int → long , float → double...)
-
Narrowing Conversion
대상 Type들이 같은 리터럴을 다루지만, 변환될 타입이 이전에 지니고 있던 타입보다 작은 경우 Casting을 통해 변환할 수 있는 것을 말한다. 내부의 값에 따라 OverFlow가 발생할 수 있다.
(int → short, double → float)
-
String Conversion
Wrapper Class의. toString()을 통해 변환되는 것을 말하거나 혹은 parse를 통한 경우를 말한다.
Integer numA = 100; String str = num.toString(); int nunB = integer.parseInt(str);
-
Boxing/Unboxing Conversion (JDK 5+)
Wrapper Class 가 Primitive Type 과의 연산이나 값 저장이 이루어지는 경우에 컴파일러에서 자동적으로 변환해주는 것을 말한다.
int numA = 10; Integer numB = 10; // Integer.valueOf(10) _ 오토박싱 int result = numA + numB; // numB.intValue() - int 10 _ 언박싱
-
Numeric Promotions
이진 연산 시에 변수들의 크기가 호환되지 않는 경우, 호환성을 위해 지원하는 규칙들을 말한다.
- 하나의 변수가 Double이면, 다른 변수도 Double로 변경된다.
- 하나의 변수가 float이면, 다른 변수도 float으로 변경된다.
- 하나의 변수가 long이면, 다른 변수도 long으로 변경된다.
- 위의 상황을 만족시키지 않는 경우 Int로 간주한다.
Casting
어떠한 타입을 다른 타입으로 명시적인 변환을 하는 것을 Casting이라고 한다.
- Primitive Type 간의 Type 변환
- 구현, 상속 관계의 Class 간의 Type 변환
구현, 상속 관계의 Class 간의 Type 변환
public class Casting {
public static void main(String[] args) {
// Up Casting
// 상위 클래스의 공통 메서드, 상태는 하위 클래스에서 사용 가능하다.
// 하위 클래스의 재정의, 메서드, 상태는 상위 클래스에서 사용이 불가능하다.
Parent child = new Child();
child.name = "name";
child.getDegree(); // Child의 메서드 접근 - 컴파일 에러
// Down Casting
Child childTwo = (Parent) childOne;
childTwo.getDegree(); // 사용 가능
}
}
1차 및 2차 배열 선언하기
// 1차원 Int 배열 생성.
// 정수 값을 넘김으로써 그 길이 만큼의 배열을 생성할 수 있다.
int[] numArrA = new int[**length**];
//혹은
int[] numArrA = {10,20,30,40,50};
int[][] numArrB = new int[length][length];
//혹은
int[][] numArrB = {{10,20}, {30,40}};
// for을 통한 초기화 방식
int[][] numArrB = new int[10][10];
for (int loop = 0; loop < numArrB.length; loop++) {
for (int innerLoop = 0; innerLoop < numArrB[loop].length; innerLoop++) {
numArrB[loop][innerLoop] = 10;
}
}
//혹은
int[][] numArrC = new int[10][10];
for (int loop = 0; loop < numArrB.length; loop++) {
Arrays.fill(numArrC[loop], 10);
}
// 출력 방식
for (int[] ints : numArrB) {
System.out.println("ints = " + ints);
for (int anInt : ints) {
System.out.println("anInt = " + anInt);
}
}
// 혹은
System.out.println("numArrB = " + Arrays.deepToString(numArrB));
Type Inference (타입 추론) , var
Type Inference 이란 정적인 언어에서 컴파일러가 컴파일 시점에서 변수를 초기화하는 리터럴을 판단하여 해당 타입으로 변환하는 것을 말한다.
자바는 JDK 10부터 Local Scope 내에서 var이라는 새로운 Type을 지원하게 되었다.
사용 시 주의점
- 초깃값 (리터럴)이 없다면 컴파일 에러가 발생한다.
var num;
- null로 초기화하면 작동하지 않는다.
var num = null;
- local 변수가 아니라면 작동하지 않는다.
public num = "String";
- 람다 표현식에는 var 타입의 변수를 사용할 수 없다.
var foo = (String s) → s.length() > 10;
- 타입 없이 배열 초깃값을 넘겨도 작동하지 않는다.
var arr = { 1, 2, 3 };
public void someMethod() {
var str = "Hello world";
assertTrue(str instanceof String);
var num = 10;
var numB = 10.10D;
System.out.println(numB+num); // 20.1
}
참고한 자료.
Java Primitives versus Objects (https://www.baeldung.com/java-primitives-vs-objects)
Introduction to Java Primitives (https://www.baeldung.com/java-primitives#:~:text=The eight primitives defined in, objects and represent raw values.)
Java Primitive Conversions (https://www.baeldung.com/java-primitive-conversions)
Variable Scope in Java (https://www.baeldung.com/java-variable-scope)
Java 10 LocalVariable Type-Inference (https://www.baeldung.com/java-10-local-variable-type-inference)
자바의 신
'Live Study' 카테고리의 다른 글
Live Study_Week 06. 상속 (0) | 2020.12.21 |
---|---|
Live Study_Week 05. 클래스 (0) | 2020.12.15 |
Live Study_Week 04. 제어문 + 과제 (0) | 2020.12.01 |
Live Study_Week 03. 연산자 (0) | 2020.11.24 |
Live Study_Week 01. JVM 은 무엇이며, 자바 코드는 어떻게 실행하는 것인가. (0) | 2020.11.13 |
- Total
- Today
- Yesterday
- Switch
- rabbitmq
- Cache Design
- JPA
- spring
- Data Locality
- Local Cache
- lambda
- AMQP
- Url
- 소비자 관점의 api 설계 패턴과 사례 훑어보기
- mybatis
- HTTP
- spring AOP
- URN
- RPC
- 게으른개발자컨퍼런스
- Distributed Cache
- hypermedia
- JVM
- 게으른 개발자 컨퍼런스
- java
- URI
- Global Cache
- RESTful
- configuration
- THP
- cglib
- JDK Dynamic Proxy
- 근황
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |