반응형
목표
자바가 제공하는 다양한 연산자를 학습합니다.
학습할 것
- 산술 연산자
- 비트 연산자
- 관계 연산자
- 논리 연산자
- instanceof
- assignment(=) operator
- 화살표(->) 연산자
- 3항 연산자
- 연산자 우선 순위
- (optional) Java 13. switch 연산자
산술 연산자
수학적 계산( 사칙 연산 ) 에 사용되는 연산자입니다. ( +, -, *, /, % )
연산자 | 설명 | 에러 | |
+ | 이항 더하기 연산자 | 하나의 숫자를 다른 숫자에 더합니다. | |
단항 플러스 연산자 |
숫자 프로모션을 트리거하는 것과 별개의 기능을 수행 | ||
문자열 연결을 수행 | 두 개의 문자열을 조인하여 세 번째 문자열을 제공합니다. | ||
- | 이항 더하기 연산자 | 다른 숫자에서 하나의 숫자를 뺍니다 | |
단항 플러스 연산자 (-1) | 피연산자를 0에서 뺀 것과 같습니다. | ||
* | 이항 연산자 | 한 숫자에 다른 숫자를 곱합니다. | |
/ | 이항 연산자 ( n / d = q ) |
한 숫자를 다른 숫자로 나눕니다. Java 정수부는 0을 반올림.Java 부동 소수점 분할의 기본 아이디어는 결과 q 가 d . q = n 를 만족시키는 데 가장 가까운 값입니다. d* q = n . 부동 소수점 나누기의 결과는 IEEE 754 산술 규칙에 따라 결정됩니다. |
분모가 0이면 ArithmeticException |
% | 이항 연산자 | 한 숫자를 다른 숫자로 나눌 때 나머지를 계산합니다. Java 프로그래밍 언어에서는 부동 소수점 피연산자도 허용합니다. 부동 소수점 나머지는 b 가 0 일 때와 같이 경계 케이스에서 INF 및 NaN 값을 생성 할 수 있습니다. |
정수 나머지 연산자의 제수 값이 0이면 an ArithmeticException |
INF | "무한"또는 INF 값은 너무 큰 숫자를 나타냅니다. +INF 값은 너무 크고 양수 인 숫자를 나타냅니다. -INF 값은 너무 크고 음수 인 숫자를 나타냅니다. INF 값은 오버플로를 일으키는 부동 연산 또는 0으로 나누는 부동 소수점 연산에 의해 생성됩니다 |
||
NAN | "무기한"/ "숫자가 아님"또는 NaN은 의미없는 작업으로 인해 발생하는 값을 나타냅니다. NaN 값은 0을 0으로 나누거나 0을 나머지로 계산하여 생성됩니다 |
//Please don't change class name 'Main'
class Main {
public static void main(String[] args) {
// result 의 값은 3
int result = 1 + 2;
System.out.println(result);
// result 의 값은 2
result = result - 1;
System.out.println(result);
// result 의 값은 4
result = result * 2;
System.out.println(result);
// result 의 값은 2
result = result / 2;
System.out.println(result);
// result 의 값은 10
result = result + 8;
// result 의 값은 3
result = result % 7;
System.out.println(result);
String firstString = "This is";
String secondString = " a concatenated string.";
String thirdString = firstString+secondString;
System.out.println(thirdString);
}
}
더보기
// java cat Main.class ( 바이트 코드 )
????;5
java/lang/Object<init>()V
java/lang/SystemoutLjava/io/PrintStream;
java/io/PrintStreamprintln(I)This i a concatenated string.
makeConcatWithConstants8(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
(Ljava/lang/String;)VMainCodeLineNumberTablemain([Ljava/lang/String;)V
SourceFile Main.javaBootstrapMethods(
)*+
,$java/lang/invoke/StringConcatFactory?(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite.
InnerClasses1%java/lang/invoke/MethodHandles$<MN,-?:??!B/lang/invoke/MethodHandlesLookup *??! "# ?S<?
#*/4;>AJR $%'-/
피연산자 및 결과 유형 및 숫자 승격
연산자는 숫자 피연산자가 필요하며 숫자 결과를 생성합니다. 피연산자 유형은 java.lang 에서 정의 된 임의의 원시 숫자 유형 (즉, byte , short , char , int , long , float 또는 double )이거나 숫자 래퍼 유형 일 수 있습니다. ie( Byte , Character , Short , Integer , Long , Float 또는 Double .)
결과 유형은 다음과 같이 피연산자 또는 피연산자 유형에 따라 결정됩니다.
- 피연산자 중 하나가 double 또는 Double 이면 결과 유형은 double 입니다.
- 그렇지 않으면 피연산자 중 하나가 float 또는 Float 이면 결과 유형은 float 입니다.
- 그렇지 않으면, 피연산자 중 하나가 long 또는 Long 이면 결과 유형은 long 입니다.
- 그렇지 않은 경우 결과 유형은 int 입니다. 여기에는 byte , short , char 피연산자와`int.
연산의 결과 유형에 따라 산술 연산이 수행되는 방식과 피연산자가 처리되는 방식이 결정됩니다.
- 결과 유형이 double 이면 피연산자가 double 으로 승격되고 연산은 64 비트 (배정 밀도 이진) IEE 754 부동 소수점 산술을 사용하여 수행됩니다.
- 결과 유형이 float 이면 피연산자가 float 로 승격되고 연산은 32 비트 (단 정밀도 2 진수) IEE 754 부동 소수점 산술을 사용하여 수행됩니다.
- 결과 유형이 long 경우, 피연산자는 long 으로 승격되고 연산은 64 비트 부호있는 2의 보수 2 진 정수 산술을 사용하여 수행됩니다.
- 결과 유형이 int 이면 피연산자가 int 로 승격되고 연산은 32 비트 부호있는 2의 보수 2 진 정수 연산을 사용하여 수행됩니다.
- ( 정수 타입의 연산의 결과가 int타입으로 나온느 이유는 자바가상기계(JVM)이 기본적으로 32bit 단-위로 계산하기 때문입니다. )
프로모션은 다음 두 단계로 수행됩니다.
- 피연산자 유형이 래퍼 유형 인 경우, 피연산자 값은 해당 프리미티브 유형의 값에 unboxed 됩니다.
- 필요한 경우 기본 유형이 필수 유형으로 승격됩니다.
- int 또는 long 으로 정수를 승격하는 것은 손실이 적습니다.
- double 하는 float 프로모션은 손실이 적습니다.
- 부동 소수점 값으로 정수를 승격하면 정밀도가 떨어질 수 있습니다. 변환은 IEE 768 "가장 가까운 값으로 반올림"의미론을 사용하여 수행됩니다.
비트 연산자와 논리 연산자
- 보수 ( ~ ) 연산자는 하나의 피연산자 비트를 비트 또는 논리 반전하는 단항 연산자입니다.
- AND ( & ) 연산자는 두 개의 피연산자의 비트 또는 논리 "and"를 수행하는 이항 연산자입니다.
- OR ( | ) 연산자는 2 개의 피연산자의 비트 또는 논리 "포함 또는"을 수행하는 2 진 연산자입니다.
- XOR ( ^ ) 연산자는 두 개의 피연산자의 비트 또는 논리 "배타적 논리합"을 수행하는 이항 연산자입니다.
연산자는 실제로 모든 32 또는 64 비트의 피연산자 또는 피연산자를 병렬로 연산합니다.
~ 연산자는 부울 값을 뒤집거나 정수 피연산자의 모든 비트를 변경하는 데 사용됩니다.
& 연산자는 정수 피연산자의 비트 중 일부를 "마스킹"하는 데 사용됩니다.
int word = 0b00101010;
int mask = 0b00000011; // Mask for masking out all but the bottom
// two bits of a word
int lowBits = word & mask; // -> 0b00000010
int highBits = word & ~mask; // -> 0b00101000
연산자는 두 피연산자의 진리 값을 결합하는 데 사용됩니다.
int word2 = 0b01011111;
// Combine the bottom 2 bits of word1 with the top 30 bits of word2
int combined = (word & mask) | (word2 & ~mask); // -> 0b01011110
^ 연산자는 비트 전환 또는 "뒤집기"에 사용됩니다.
int word3 = 0b00101010;
int word4 = word3 ^ mask; // -> 0b00101001
관계 연산자 (<, <=,>,> =)
< , <= , > 및 >= 연산자는 숫자 유형 비교를위한 이항 연산자입니다.
이러한 연산자의 결과 유형은 모든 경우에 boolean 입니다. 관계 연산자를 사용하여 숫자를 다른 유형과 비교할 수 있습니다.
int i = 1;
long l = 2;
if (i < l) {
System.out.println("i is smaller");
}
class Main {
public static void main(String[] args) {
char i = 'A';
long l = 2;
if (i < l) {
System.out.println("i is smaller");
}
else{
System.out.println("l is smaller"); //!!!! 이게 출력된다.
}
}
}
더보기
// 바이트 코드
????;"
java/lang/Object<init>()V
java/lang/SystemoutLjava/io/PrintStream;
i is smaller
java/io/PrintStreamprintln(Ljava/lang/String;)V
StackMapTable j is smallerMainCodeLineNumberTablemain([Ljava/lang/String;)V
SourceFile Main.java ? "A<A ??? ??
? ??
? !%
이러한 연산자를 사용하여 문자열, 숫자 배열 등을 비교할 수 없습니다 .
- 피연산자 중 하나가 박스형이면 unbox입니다.
- 현재 피연산자 중 하나가 byte , short 또는 char 이면 int 로 승격됩니다.
- 피연산자의 유형이 동일하지 않으면 "더 작은"유형의 피연산자가 "더 큰"유형으로 승격됩니다.
- 결과는 int , long , float 또는 double 값에 대해 비교가 수행됩니다.
instanceof
객체가 특정 클래스 / 인터페이스 유형인지 여부를 확인합니다. instanceof 연산자는 다음과 같이 작성됩니다.
객체 타입을 확인하는데 사용하는 연산자. 해당 여부를 true, false 로 알려준다. 부모 객체의 인스턴스인지 자식 객체인지 를 알려줄 때 사용합니다.
객체 instanceof 클래스
( Object reference variable ) instanceof (class/interface type)
class A {}
class B extends A {}
public static void main(String[] args) {
A a = new A();
B b = new B();
System.out.println(a instanceof A); // true
System.out.println(b instanceof A); // true
System.out.println(a instanceof B); // false
System.out.println(b instanceof B); // true
}
더보기
바이트 코드
????;!
java/lang/Object<init>()A
B
java/lang/SystemoutLjava/io/PrintStream;
java/io/PrintStreamprintln(Z)VMainCodeLineNumberTablemain([Ljava/lang/String;)V
SourceFile Main.java!? 9?Y? L?
Y?
+???
,?
??
$
8 %
assignment(=) operator :: 할당 연산자
값을 변수에 할당할 때 쓰는 연산자입니다.
주소 할당과 값 할당을 다르게 생각해야합니다.
- 깊은 복사와 얕은 복사
- 얕은 복사 = 주소를 이어준다. B 를 수정하는 것은 A를 수정하는 것과 같습니다.
- 깊은 복사 = 값을 복사해서 제대로 복사합니다.
- 배열 복사 메서드 예 : 원본배열.clone(), Arrays.copyOf(원본배열, 내가 원하는 length까지) System.copyOfRange(원본배열, 원하는 시작점, 원하는 끝점), System.arrayCopy() (지정된 배열을 대상 배열의 지정된 위치에 복사해줍니다.)
- 2차원 배열의 경우 1차원 배열과 같은 방식을 취하면, a[x][y]는 얕은 복사가 된다. 무조건 반복문을 돌려서 일일이 복사해줘야합니다.
import java.util.Arrays;
public class Array_Copy{
public static void main(String[] args) {
int[] a = { 1, 2, 3, 4 };
int a2[][] = {{1,2,3},{4,5,6,},{7,8,9}};
int[] shallowCopy = a; // 얕은 복사 => 주소만 복사함
/* 1-1번. 반복문 */
int[] b1 = new int[a.length];
for (int i = 0; i < a.length; i++) {
b1[i] = a[i];
}
/* 1-2번. clone -> 가장 보편적 */
int[] b2 = a.clone();
/* 1-3번. Arrays.copyOf() -> 가변 길이(끝) */
int[] b3 = Arrays.copyOf(a, a.length);
/* 1-4번. AArrays.copyOfRange() -> 가변 길이(시작, 끝) */
int[] b4 = Arrays.copyOfRange(a, 1, 3);
/* 1-5번. System.arraycopy -> 원하는 위치에 */
int[] b5 = new int[a.length];
System.arraycopy(a, 0, b5, 0, a.length);
/* 2-1번. 이중배열 이중 반복문으로 생성 */
int[][] b21 = new int[a2.length][a2[0].length];
for(int i=0; i<a2.length; i++) {
for(int j=0; j<a2[i].length; j++) {
b21[i][j] = a2[i][j];
}
}
/* 2-2번. 이중배열 1 반복문 + System.arraycopy으로 생성 */
int b22[][] = new int[a2.length][a2[0].length];
for(int i=0; i<b22.length; i++){
System.arraycopy(a2[i], 0, b22[i], 0, a2[0].length);
}
}
}
더보기
바이트코드
????;*
java/lang/Object<init>()[I
clone()Ljava/lang/Object;
java/util/ArrayscopyOf([II)[I
copyOfRang([III)[I
ava/lang/System arraycopy*(Ljava/lang/Object;ILjava/lang/Object;II)V[[I
StackMapTable'[Ljava/lang/String;([Ljava/lang/String;)V
SourceFileArray_Copy.java!!*??" #$!?
?
YOYOYOYOL?Y?
YOYOYOSY?
YOOYOSY?
YOOY OSM+N+??
:+?:+??O????+? ?:++??
+??,?,2??: 6
,??+6
,
2??
2
,
2
.O?
???
???,?,2??:
6
??
2
2,2???
???"^S[ e
}???????????!?"!
%%?^&??7
&? ????()%
화살표 연산자
Java 8 이후부터 람다 연산자 ( -> )는 람다 식을 도입하는 데 사용되는 연산자입니다. 다음 예에서 볼 수 있듯이 두 가지 공통적 인 구문이 있습니다. 람다 표현식은 익명 함수, 또는 함수 인터페이스 를 구현하는 익명 클래스의 인스턴스를보다 정확하게 정의합니다.
a -> a + 1 // a lambda that adds one to its argument
a -> { return a + 1; } // an equivalent lambda using a block.
람다식
Lambda 표현식은 표현식을 사용하는 단일 메서드 인터페이스를 구현하는 명확하고 간결한 방법을 제공합니다.
// lambda 안씀
JButton btn = new JButton("My Button");
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Button was pressed");
}
});
인터페이스 ActionListener는 하나의 메서드 만 정의 actionPerformed()하므로 기능적 인터페이스이므로 Lambda 식을 사용하여 표준 코드를 대체 할 수 있습니다. 위의 예는 다음과 같이 Lambda 표현식을 사용하여 다시 작성할 수 있습니다.
// 람다씀
JButton btn = new JButton("My Button");
btn.addActionListener(e -> {
System.out.println("Button was pressed");
});
삼항연산자
삼항 연산자는 자바에서 유일하게 피연산자를 세 개나 가지는 조건 연산자입니다.
삼항 연산자의 문법은 다음과 같습니다. 물음표(?) 앞의 조건식에 따라 결괏값이 참(true)이면 반환값1을 반환하고, 결괏값이 거짓(false)이면 반환값2를 반환합니다.
조건식 ? 반환값1 : 반환값2
int num1 = 5, num2 = 7;
int result;
result = (num1 - num2 > 0) ? num1 : num2;
System.out.println("두 정수 중 더 큰 수는 " + result + "입니다.");
//두 정수 중 더 큰 수는 7입니다.
더보기
//바이트코드
????;/
java/lang/Object<init>()V
java/lang/SystemoutLjava/io/PrintStream;
makeConcatWithConstants(I)Ljava/lang/String;
StackMapTableStreamprintln(Ljava/lang/String;)VMainCodeLineNumberTablemain([Ljava/lang/String;)V
SourceFile Main.javaBootstrapMethods"
#$%
&$java/lang/invoke/StringConcatFactory?(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite()두 정수 중 더 큰 수는 입니다.
InnerClasses+%java/lang/invoke/MethodHandles$Lookup-java/lang/invoke/MethodHandlesLookup!*?? <=?>??? ?@!')
*,.%
연산자 우선 순위
java13 switch 연산자
입력값이 정형화되어 있고, 조건이 많은 경우 if문보다는 switch/case문을 쓰는것이 가독성에서 좀 더 유리하다.
switch(입력변수) {
case 입력값1: ...
break;
case 입력값2: ...
break;
...
default: ... // 그 외
break;
}
더보기
public class SwitchDemo {
public static void main(String[] args) {
int month = 8;
String monthString = "";
switch (month) {
case 1: monthString = "January";
break;
case 2: monthString = "February";
break;
case 3: monthString = "March";
break;
case 4: monthString = "April";
break;
case 5: monthString = "May";
break;
case 6: monthString = "June";
break;
case 7: monthString = "July";
break;
case 8: monthString = "August";
break;
case 9: monthString = "September";
break;
case 10: monthString = "October";
break;
case 11: monthString = "November";
break;
case 12: monthString = "December";
break;
default: monthString = "Invalid month";
break;
}
System.out.println(monthString);
}
}
참고문헌
tcpschool.com/java/java_operator_etc
coding-factory.tistory.com/548
riptutorial.com/fr/java/topic/91/expressions-lambda
반응형
'스프링, 자바' 카테고리의 다른 글
why we use spring? (0) | 2020.12.02 |
---|---|
제어문 (4) | 2020.11.28 |
mvc 아키텍처 (0) | 2020.11.18 |
mocMvc Controller Test (0) | 2020.11.18 |
타임리프 찾아본 로그 (0) | 2020.11.16 |