자바 연산자 (2)

Tina Jeong·2021년 1월 13일
0

Re-자바

목록 보기
6/16

자바 연산자 (1)에서는 기본적인 연산자들에 대해 정리했고, 이번 포스트에서는 자바가 특별히(?) 지원하는 연산자들을 정리해본다.

instanceof


인스턴스이름 instaceof 인스턴스타입

instanceof 연산자는 인스턴스 비교를 위한 관계연산자로 이해하면 된다. 인스턴스이름(물론 해당 부분에 리터럴이 들어갈수도 있다)이 인스턴스의 타입이면 true가 되고, 아니라면 false가 된다.

instanceof는 클래스 타입 캐스팅 전에 타입 변환 가능 여부를 체크하는데 많이 사용된다. 더불어 객체가 null이라면 false를 리턴 해주니-null은 어떤 타입에도 속하지 않으므로- 편하게 사용할 수 있다.

if(obj instanceof Point){
	Point p = (Point) obj;
    	...
}

화살표(->) 연산자


화살표 연산자는 Java 8 버전부터 추가된 것으로, 람다 표현식과 함께 사용된다. 람다표현식은 일종의 익명 함수라고 볼수 있는데, 익명 함수를 이해하기 위해서는 먼저 익명 클래스 Anonymous class의 개념을 먼저 이해해야 한다.

익명 클래스란?

익명 클래스란 클래스 instantiation과 동시에 클래스를 정의하는 클래스를 의미한다. 특정 클래스가 여러번 호출되지 않거나, 클래스 내부에 필드나 여러개의 메소드를 정의할 필요가 있는 경우 익명클래스로 정의해 사용할 수 있다.

interface Smartphone {
	void setOs();
    	void printOs(String osName);
}
 Smartphone iPhone = new Smartphone() {
            String os = "iOS";
            void setOs() {
                printOs(os);
            }
            
            void printOs(String osName) {
                os = osName;
                System.out.println("This is " + os);
            }
};

익명 클래스의 특징

  • new를 사용한다.
  • instantiation시 parameter가 없어야 한다.(빈 parenthesis)
  • parenthesis 뒤에 interface를 implement하거나 class를 extends하는 내용이 와야 한다.

Anonymous class ⊂ Inner class

익명 클래스는 Inner class의 일종이다. 고로 다음의 특징도 가진다.

  • 클래스 내에 static 변수를 선언할 수 없다.(static final은 가능)
  • Outer class의 멤버변수나 scope 내의 지역변수에 접근할 수 있다.

one step forward..

익명 클래스가 일반적인 클래스 정의 방법에 비해 간단하지만, 클래스 내부에 필드도 필요하지 않고, 딱 하나의 메소드만 존재하는 경우엔 익명 클래스 문법 조차 과하게 느껴질 수 있다. 람다 표현식을 이용한다면 single method class에 대해 간편하게 처리할 수 있게된다.

람다식

뿐만 아니라, 람다식은 메소드를 변수처럼 다룰 수 있다는 측면에서 편리하다. 대부분의 메소드들은 클래스에 종속된 멤버함수의 형태로 제공되는 형태이지만, 람다식은 클래스에 종속되지 않는다.

문법

FunctionalInterface f = (arg1, arg2, ...) -> {implementation};

인자를 0개부터 받아서 implementation 부분에서 활용할 수 있다. argument list 부분의 인자가 하나라면 구현부의 소괄호를 생략할 수 있으며, statement 개수가 1개이면 중괄호를 생략할 수 있다.

람다식은 앞서 언급한 코드의 간결성 뿐 아니라, stream을 통한 데이터의 독립적 처리에도 많이 쓰인다. 성능 이슈는 또 다른 문제이고.

() -> System.out.println("0 argument");
a -> {
       if (a > 0) System.out.println(a);
       System.out.println("single argument")
};

잠깐 사담
출처: 프로그래머 합창단 Scalability - Write in Go

자바 문법은 쓸데없이 길다는 말이 많다. closure, anonymous class, lambda, method reference 등의 feature들은 뭐라도 줄이기 위한 자바 언어 개발자의 부던한 노력의 결과 아니었을까..물론 그 안에 함수형 프로그래밍 등의 철학은 있겠지만.

연산자 우선 순위


첫번째 연산자 포스트와 아울러 산술, 관계, 논리, 비트, 증감, 삼항, 대입, instanceof, -> 연산자를 정리했다. 연산자 우선순위를 굳이 외울 필요까진 없어서 기억할 포인트를 정리했다.
생활코딩에 연산자 우선순위 표가 잘 정리되어 있으니 자세한 우선순위는 해당 표를 참고하면 될 듯하다.

소괄호가 1순위

일반적인 상황에서는 다음의 내용만 기억하면 된다. *, /, %의 우선순위가 +, - 연산 보다 높다. 또한, 논리연산자!과, 증감 연산자 ++, --의 우선순위는 *, /, %보다 높다. 다만, 소괄호로 묶은 부분이 연산에서 최우선 순위가 된다.

int a = 2-3*4; //-10
int b = (2-3)*4; // -4

산술연산이 관계연산을 만드니까, 관계 연산자>,<,==,!=가 산술연산보다 우선순위가 낮다. 또한, 관계 연산이 논리연산을 만드니까 논리연산&&, ||의 우선순위가 낮다. 다만, 여기에서도 소괄호로 묶이면 연산의 우선순위가 달라진다.

if(!foo() || a<b) System.out.println("소괄호 없음");
if(!(foo() || a<b)) System.out.println("소괄호 있음");

static boolean foo() {
    return false;
}

결과는 "소괄호 없음"만 프린트된다.

삼항연산자는 대입연산자를 제외하고 최하위

=, *=, /=, +=, -=, %= 등의 대입연산자를 제외하고는 삼항연산자가 제일 순위가 낮다는 사실을 기억하면 일반적인 프로그래밍에서는 의도에 맞게 프로그램이 돌아갈 것이다.

참고
https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html
https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
https://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html
https://opentutorials.org/course/1223/5331
Java in a Nutsell, 7th Edition

계속해서 문서를 업데이트하고 있습니다. 언제든지 댓글피드백 남겨주세요. 😉

profile
Keep exploring, 계속 탐색하세요.

0개의 댓글