# 4.3.7 연산자 by ys

Spring Expression Language는 다음과 같은 종류의 연산자를 지원합니다 :

* [관계 연산자](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#expressions-operators-relational)
* [논리 연산자](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#expressions-operators-logical)
* [수학 연산자](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#expressions-operators-mathematical)
* [배정 연산자](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#expressions-assignment)

**관계 연산자**

{% hint style="info" %}

* 같음 (`==`)
* 같지 않음 (`!=`)
* 작음 (`<`)
* 작거나 같음 (`<=`)
* 큼 (`>`)
* 크거나 같음 (`>=`)
  {% endhint %}

표준 연산자 표기법을 사용하여 관계 연산자 (같음, 같지 않음, 같지 않음, 작음 이하, 더 크고 같음)가 지원됩니다. 다음 목록은 연산자의 몇 가지 예를 보여줍니다.

```java
// evaluates to true
boolean trueValue = parser.parseExpression("2 == 2").getValue(Boolean.class);

// evaluates to false
boolean falseValue = parser.parseExpression("2 < -5.0").getValue(Boolean.class);

// evaluates to true
boolean trueValue = parser.parseExpression("'black' < 'block'").getValue(Boolean.class);
```

|   | <p>보다 크거나 작은 <code>null</code>에 대한 비교는 단순한 규칙 을 따른다 : <code>null</code>아무것도 아닌 것으로 취급된다 (그것은 0이 아니다). 결과적으로 다른 값은 항상 <code>null</code> 보다 크고 ( <code>X > null</code>항상 <code>true</code>) 아무것도없는 것보다 적은 값은 없습니다. ( <code>X < null</code>항상 <code>false</code>).</p><p>대신 숫자 비교를 선호하는 경우 0 에 대한 비교를 위해 숫자 기반  <code>null</code>비교를 사용하지 마십시오. (예 : <code>X > 0</code>또는 <code>X < 0</code>).</p> |
| - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

표준 관계 연산자 외에도 SpEL은 `instanceof`와 정규 표현식 기반 `matches`연산자를 지원합니다 . 다음 목록은 두 가지 예를 보여줍니다.

{% hint style="info" %}
Java에서 super타입에 대한 연산을 위해 instanceof를 표현식으로 사용할 수 있다.
{% endhint %}

{% hint style="info" %}
matches를 이용한 정규표현식을 지원한다.
{% endhint %}

```java
// evaluates to false
boolean falseValue = parser.parseExpression(
        "'xyz' instanceof T(Integer)").getValue(Boolean.class);

// evaluates to true
boolean trueValue = parser.parseExpression(
        "'5.00' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);

//evaluates to false
boolean falseValue = parser.parseExpression(
        "'5.0067' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);
```

|   | 프리미티브 유형은 래퍼 유형에 따라 즉시 박스 처리되므로 1 instanceof T (Integer)가 예상대로 true로 평가되는 동안 1 instanceof T (int)는 false로 평가됩니다. |
| - | ---------------------------------------------------------------------------------------------------------------- |

{% hint style="info" %}
**Wrapper 클래스**

자바의 데이터 타입은 다음의 표와 같이 프리미트브 타입과 레퍼런스 타입으로 나뉜다.

프리미티브 타입은 수치, 문자등 간단한 데이터를 표현할 수 있는 타입이고 그밖의 제이터 타입은 모두 레퍼런스 타입으로 분류된다.

경우에 다라서는 프리미티브 타입의 데이터를 객체로 만들어야할 필요가 있는데 이러한경우 사용하는게 **Wrapper클래스**이다.

Wrapper클래스 : 프리미티브 타입의 값을 담는 객체를 생성하는 것이다.
{% endhint %}

| 클래스이름     | 프리미티브 타입 | 간단한 예                                      |
| --------- | -------- | ------------------------------------------ |
| Byte      | byte     | Byte byteA = new Byte((byte) 1);           |
| Short     | short    | Short shortA = new Short((short) 231);     |
| Integer   | int      | Integer integerA = new Integer(111);       |
| Long      | long     | Long longA = new Long(10000L);             |
| Character | char     | Character characterA = new Character('나'); |
| Float     | float    | Float floatA = new Float(13.5f);           |
| Double    | double   | Double doubleA = new Double(14.55);        |
| Boolean   | boolean  | Boolean booleanA = new Boolean(true);      |

{% hint style="info" %}
표에 있는 예처럼 Wrapper클래스로 만든 객체를 Wrapper객체라고 한다.

하나의 Wrapper클래스는 하나의 프리미티값을 담을 수 있다.  값은 생성자 파라미터로 넘겨주어야 한다.\
\
출처: <https://zzdd1558.tistory.com/58> \[신입 개발자]
{% endhint %}

{% hint style="info" %}
**자동 Boxing과 자동 Unboxing**

Boxing - 프리미티브 타입의 값을 래퍼 객체로 만드는것.

Unboxing - 래퍼 객체를 프리미티브 타입의 값으로 만드는것.

ex)
{% endhint %}

| `Integer integerA =` `new` `Integer(1000)` `// Boxing` `int` `num = integerA.intValue();` `// Unboxing` |
| ------------------------------------------------------------------------------------------------------- |

{% hint style="info" %}
**자동 Unboxing**에 대해 알아 보겠습니다. 자동 Unboxing는 래퍼객체 → 프리미트브 타입 값으로의 변환을 말합니다.

&#x20;ex)
{% endhint %}

| <p><code>Integer integerObj =</code> <code>new</code> <code>Integer(30);</code>          </p><p><code>int</code> <code>sum = integerObj +</code> <code>20;</code> <code>System.out.println(sum);                    출력결과는</code> <code>50이 나온다.</code></p> |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

{% hint style="info" %}
reason - 위의 예제에서는 Integer 객체와 int 타입의 값을 더했다. +연산자는 프리미티브 타입의 값을 더하는 연산자이기 때문에

&#x20;              Integer 객체로부터 int값이 자동으로 추출된후에 더하기 연산이 실행됩니다\
\
**자동 Boxing**에 대해 알아보겠습니다. 자동 Boxing는 프리미티브 타입 값 → 래퍼 객체로의 변환을 말한다.

&#x20;ex)
{% endhint %}

| `convertDouble(new` `Double(123.45));` `convertDouble(123.45);`   `]static` `void` `convertDouble(Double convertDoubleValue){` `System.out.println(convertDoubleValue);` `}` |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

{% hint style="info" %}
reason - 위의 예제에서는 double 타입의 프리미티브값을 넘겨 Double 타입 파라미터를 받는 메소드를 호출하였습니다. 이러한 경우 double타입의 프리미트브 값을 갖는 Double 객체가 자동으로 생성되어 메소드에 넘겨집니다  <br>
{% endhint %}

각 기호 연산자는 순전히 알파벳순으로 지정할 수도 있습니다. 이렇게하면식이 포함 된 문서 형식 (예 : XML 문서)에 사용 된 기호가 특별한 의미를 갖는 문제를 피할 수 있습니다. 텍스트와 동등한 내용은 다음과 같습니다.

* `lt`( `<`)
* `gt`( `>`)
* `le`( `<=`)
* `ge`( `>=`)
* `eq`( `==`)
* `ne`( `!=`)
* `div`( `/`)
* `mod`( `%`)
* `not`( `!`).

모든 텍스트 연산자는 대소 문자를 구분하지 않습니다.

**논리 연산자**

SpEL은 다음과 같은 논리 연산자를 지원합니다 :

* `and`
* `or`
* `not`

다음 예에서는 논리 연산자를 사용하는 방법을 보여줍니다.

```java
// -- AND --

// evaluates to false
boolean falseValue = parser.parseExpression("true and false").getValue(Boolean.class);

// evaluates to true
String expression = "isMember('Nikola Tesla') and isMember('Mihajlo Pupin')";
boolean trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);

// -- OR --

// evaluates to true
boolean trueValue = parser.parseExpression("true or false").getValue(Boolean.class);

// evaluates to true
String expression = "isMember('Nikola Tesla') or isMember('Albert Einstein')";
boolean trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);

// -- NOT --

// evaluates to false
boolean falseValue = parser.parseExpression("!true").getValue(Boolean.class);

// -- AND and NOT --
String expression = "isMember('Nikola Tesla') and !isMember('Mihajlo Pupin')";
boolean falseValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);
```

**수학 연산자**

{% hint style="info" %}

* 더하기 (+) 연산자를 숫자, 날짜, 문자열에 사용할 수 있다.
* 빼기(-) 연산자를 숫자, 날짜에 사용할 수 있다.
* 곱하기(\*), 나누기(/), 나머지(%)에 대한 연산은 숫자에만 사용 할 수 있다.
* 연산자 우선 순위 법칙이 적용된다.
  {% endhint %}

숫자와 문자열 모두에서 더하기 연산자를 사용할 수 있습니다. 빼기, 곱하기 및 나누기 연산자는 숫자에만 사용할 수 있습니다. 모듈러스 (%) 및 지수 출력 (^) 연산자를 사용할 수도 있습니다. 표준 운영자 우선 순위가 적용됩니다. 다음 예제는 사용중인 수학 연산자를 보여줍니다.

```java
// Addition
int two = parser.parseExpression("1 + 1").getValue(Integer.class);  // 2

String testString = parser.parseExpression(
        "'test' + ' ' + 'string'").getValue(String.class);  // 'test string'

// Subtraction
int four = parser.parseExpression("1 - -3").getValue(Integer.class);  // 4

double d = parser.parseExpression("1000.00 - 1e4").getValue(Double.class);  // -9000

// Multiplication
int six = parser.parseExpression("-2 * -3").getValue(Integer.class);  // 6

double twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double.class);  // 24.0

// Division
int minusTwo = parser.parseExpression("6 / -3").getValue(Integer.class);  // -2

double one = parser.parseExpression("8.0 / 4e0 / 2").getValue(Double.class);  // 1.0

// Modulus
int three = parser.parseExpression("7 % 4").getValue(Integer.class);  // 3

int one = parser.parseExpression("8 / 5 % 2").getValue(Integer.class);  // 1

// Operator precedence
int minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Integer.class);  // -21
```

**배정 연산자**

특성을 설정하려면 대입 연산자 ( `=`)를 사용하십시오 . 이것은 일반적으로 `setValue`호출 내에서 이루어 지지만 `getValue`호출 내에서 수행 될 수도 있습니다. 다음 목록은 할당 연산자를 사용하는 두 가지 방법을 보여줍니다.

```java
Inventor inventor = new Inventor();
EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();

parser.parseExpression("Name").setValue(context, inventor, "Aleksandar Seovic");

// alternatively
String aleks = parser.parseExpression(
        "Name = 'Aleksandar Seovic'").getValue(context, inventor, String.class);
```
