문장
메서드와 생성자의 본문은 문장의 나열입니다. 이 장의 문장 외의 형태는 Unsupported method statement: … 오류입니다.
문장을 끝내는 규칙
섹션 제목: “문장을 끝내는 규칙”- 단순 문장(선언·대입·호출·
return·throw·break·continue·print)은 세미콜론으로 끝냅니다. 빠뜨리면Method statement must end with semicolon: print("x")오류입니다. if·while·for·try처럼 블록으로 끝나는 문장 뒤에는 세미콜론을 쓰지 않습니다.do { … } while (조건);은 세미콜론으로 끝냅니다.- 독립된 블록
{ … }만 따로 쓸 수는 없습니다. 범위를 나누려면 메서드로 분리합니다. - 식만 있는 문장은 호출·생성자 호출·
await만 허용합니다.a + b;,x;는 거절됩니다.
지역 변수
섹션 제목: “지역 변수”[final] 타입 이름 = 초기값;[final] var 이름 = 초기값;int count = 0;var name = "Kim";final double rate = 0.5;List<string> names = [];string? note = null;- 초기값이 필요합니다.
int x;는Unsupported method statement: int x오류입니다. 나중에 값을 정한다면int x = 0;처럼 기본값으로 선언합니다. - 한 문장에 변수 하나만 선언합니다(
int a = 1, b = 2;는 거절). final지역 변수는 다시 대입하면Cannot assign to final variable 'rate'.오류입니다. 지역 변수에const는 쓸 수 없습니다.void지역 변수는Local variable must not use void type.오류입니다.- 초기값에서 자기 자신을 참조할 수 없습니다 (
Local variable 'x' cannot reference itself in its initializer.). 문자 하나짜리 변수 이름과 숫자 접미사가 겹치는float f = 1.5f;같은 경우도 이 오류가 날 수 있으므로float ratio = 1.5f;처럼 의미 있는 이름을 사용하세요.
- 지역 변수는 선언한 뒤부터, 선언한 블록 안에서만 사용합니다 (
Undefined variable 'x'.). - 한 메서드 안에서는 중첩 블록이어도 같은 이름을 다시 선언할 수 없습니다 (
Duplicate local variable 'i' in method 'main'.). 서로 독립된 블록(예: 두 개의 연속된for)에서는 같은 이름을 다시 쓸 수 있습니다. - 매개변수와 같은 이름의 지역 변수는 선언할 수 없습니다. 필드와 같은 이름은 가능하며 이때 필드는
this.이름으로 구분합니다.
count = count + 1;this.name = name;order.total = 0;items[0] = "first";ages["Kim"] = 31;- 왼쪽에는 변수,
객체.필드,리스트[인덱스],맵[키]를 씁니다.this,super에는 대입할 수 없습니다. - 오른쪽 값의 타입은 왼쪽에 대입 가능해야 합니다 (
Cannot assign int to string target 'name'.). - 복합 대입·증감 연산자는 미지원입니다.
| 쓰지 않는 형태 | 대신 쓰는 형태 |
|---|---|
x += 2; x -= 2; x *= 2; |
x = x + 2; x = x - 2; x = x * 2; |
i++; i--; ++i; |
i = i + 1; i = i - 1; |
a = b = 0; |
b = 0; a = 0; |
if (조건) { …} else if (조건) { …} else { …}- 조건은 괄호로 감싸고 본문은 반드시 중괄호로 감쌉니다.
if ready { … }는Invalid if statement syntax.,if (ready) run();은If statement must use a block body.오류입니다. - 조건은
bool식이어야 합니다 (If condition must be boolean but got int.).bool?도 허용하지 않습니다. else if는 개수 제한 없이 이어 쓸 수 있습니다.
while
섹션 제목: “while”while (remaining > 0) { remaining = remaining - 1;}본문을 실행하기 전에 조건을 검사합니다. 괄호·중괄호·bool 조건 규칙은 if와 같습니다.
do-while
섹션 제목: “do-while”do { attempts = attempts + 1;} while (attempts < 3);본문을 먼저 한 번 실행한 뒤 조건을 검사합니다. 마지막의 while (조건);과 세미콜론을 빠뜨리지 마세요.
for
섹션 제목: “for”for (초기화; 조건; 갱신) { …}for (int i = 0; i < names.size(); i = i + 1) { print(names[i]);}- 세 부분을 세미콜론으로 구분합니다. 각 부분은 비워 둘 수 있으며 조건을 비우면 항상 참입니다(
for (;;) { … }). - 초기화는 지역 변수 선언 또는 대입, 갱신은 대입문만 사용합니다.
i++는Unsupported for action syntax, 다른 형태는For update must be an assignment statement.오류입니다. - 초기화에서 선언한 변수는 해당
for안에서만 사용합니다. - 컬렉션을 순회할 때는 아래의
for (var item in items)를 사용할 수 있습니다. Java의 콜론 형식for (Item item : items)는 사용하지 않습니다.
class Loops { static void main() { List<string> names = ["Kim", "Lee", "Park"]; for (int i = 0; i < names.size(); i = i + 1) { print(names[i]); }
Set<string> tags = {"a", "b"}; List<string> tagList = tags.toList(); for (int j = 0; j < tagList.size(); j = j + 1) { print(tagList[j]); }
Map<string, int> ages = {"Kim": 30, "Lee": 25}; List<MapEntry<string, int>> entries = ages.entries(); for (int k = 0; k < entries.size(); k = k + 1) { print(entries[k].key + "=" + entries[k].value); } }}for-in으로 컬렉션 순회
섹션 제목: “for-in으로 컬렉션 순회”List<string> names = ["Kim", "Lee"];for (var name in names) { print(name);}- 대상은
List<T>,Set<T>또는Deque<T>입니다. 그 밖의 값은for-in iterates a List, Set or Deque, not <type>.오류입니다.Map.keys(),values(),entries()가 반환한 목록도 순회할 수 있습니다. - 요소 변수는
var또는 요소를 받을 수 있는 명시적 타입으로 선언합니다. 대상 식은 한 번 평가하고 컬렉션 순서로 방문합니다. - 본문에서 순회 중인 컬렉션의 항목을 추가·삭제하지 마세요.
break와continue는 다른 반복문과 같습니다. - 현행 콘솔·서버 생성기는 각 대상의 순회 문법으로 변환합니다. 등록 원본을 처리하는 서버 compiler가 다르면 거절될 수 있으므로 해당 응답의 진단을 확인합니다.
break와 continue
섹션 제목: “break와 continue”for (int i = 0; i < 10; i = i + 1) { if (i == 2) { continue; } if (i == 5) { break; }}break;는 가장 안쪽 반복을 끝내고,continue;는 다음 반복으로 넘어갑니다. 반복 밖에서는Break statement is only valid inside a loop.오류입니다.- 레이블(
break outer;)은 미지원입니다. 중첩 반복을 한 번에 끝내려면bool변수와 조건을 사용하거나 메서드로 분리해return합니다.
return
섹션 제목: “return”return; // void 메서드return value; // 값을 반환하는 메서드| 상황 | 진단 |
|---|---|
void 메서드에서 값 반환 |
Void method 'm' must not return a value. |
값 반환 메서드에서 return; |
Method 'm' returning int must return a value. |
| 일부 경로에 반환 없음 | Method 'f' must return int. |
| 반환 타입 불일치 | Cannot return long from method 'f' returning int. |
도달할 수 없는 문장
섹션 제목: “도달할 수 없는 문장”return, throw, break, continue 뒤나 끝나지 않는 반복 뒤에 같은 블록의 문장을 두면 거절됩니다.
static int f() { return 1; print("x"); // Unreachable statement after return: print("x")}throw
섹션 제목: “throw”throw Exception("invalid amount");- 던지는 값은
Exception또는 그 자식 클래스의 객체여야 합니다 (Throw expression must be Exception but got string.). - 기본 타입
Exception과 하위 타입ArgumentException,StateException,IndexException,IOException을 사용합니다.message로 메시지를 읽습니다. 표준 API 오류의 구체적인 하위 타입과 문구는 대상별로 다를 수 있습니다. - 사용자 예외는
Exception을 상속한 클래스로 만듭니다. 메서드에throws절은 쓰지 않습니다.
try와 catch
섹션 제목: “try와 catch”try { …} catch (예외타입 이름) { …} catch (다른예외타입 이름) { …} finally { …}class PaymentException extends Exception { public PaymentException(string message) { this.message = message; }}
class Payments { static int charge(int amount) { if (amount < 0) { throw PaymentException("negative amount"); } return amount; }
static void main() { try { int charged = charge(5); print("charged " + charged); } catch (PaymentException error) { Console.error(error.message); } catch (Exception error) { Console.error("runtime"); } }}try에는 하나 이상의catch또는finally가 필요합니다. catch의 형태는catch (타입 이름)이며catch (e)처럼 타입을 생략할 수 없습니다.- catch 타입은
Exception을 상속해야 합니다 (Catch type 'Socket' must extend Exception.). - catch 변수는 해당 catch 블록 안에서만 사용합니다. catch 블록마다 다른 변수 이름을 쓸 필요는 없습니다.
- catch는 선언 순서대로 검사하고 해당 타입과 하위 타입을 처리합니다. 어느 catch에도 맞지 않는 예외는 호출자에게 전달됩니다.
finally는 마지막 절에 쓰며 정상 완료·예외·return·break·continue로 빠져나갈 때 실행합니다.try { … } finally { … }형태도 가능합니다.- 네이티브 실행은
throw·try/catch/finally를 지원하며 범위 밖 인덱스·0 나눗셈 등 런타임 오류도Exception으로 처리할 수 있습니다. 처리하지 않은 예외는Unibase runtime error: <메시지>와 안쪽 메서드부터 최대 64줄의at <메서드> (<경로>:<줄>)위치를 출력하고 종료 코드 1로 끝납니다. - 현행 8개 콘솔·서버 생성 대상은 예외 문장을 각 언어의 예외 처리로 변환합니다. 일반 catch는
Exception으로 작성하며 경계값이 오류가 되는지와 오류 문구는 대상의 동작을 따릅니다. 실제 배포 서버의 결과는 해당 변환 진단에서 확인합니다.
print(42);print("total=" + total);print(식);은 값 하나를 한 줄로 출력하는 내장 문장입니다. 문자열이 아닌 값도 그대로 전달할 수 있습니다.print는 식이 아니라 문장입니다. 값을 반환하지 않으며 인수는 하나만 받습니다.print의 인수는 일부 의미 검사를 건너뛰므로, 타입·접근·오타를 확인하려면 값을 먼저 타입이 있는 변수에 담아 검사합니다.Console.write와Console.error는string을 받습니다. 숫자는Console.write("" + count)처럼 변환하며 한 줄 출력에는print(count)를 사용합니다.
await
섹션 제목: “await”string value = await future; // Future<string>의 결과await completed; // Future<void>의 완료 대기await의 대상은Future<T>입니다.Future<void>의 await는 값을 만들지 않으므로 독립 문장으로 사용합니다. 실패로 완료된 Future는 기다리는 지점에서 예외를 전달합니다.async메서드 수식어는 없습니다. 작업은 Async와 비동기 작업의Async.run으로 시작하거나Completer로 완료를 전달합니다.
직접 SQL 문장
섹션 제목: “직접 SQL 문장”대문자 SELECT, INSERT, UPDATE, DELETE, CREATE로 시작하는 문장은 SQL 문장입니다. 자세한 형태는 내장 언어와 schema에 있습니다.
string _name = "Kim";INSERT INTO audit (name) VALUES(_name);지원하지 않는 문장
섹션 제목: “지원하지 않는 문장”| 문장 | 대체 방법 |
|---|---|
switch, match, when |
if / else if / else |
for (T x : xs), foreach |
for (T x in xs) 또는 인덱스 for; 대상별 생성 제한 확인 |
using, try-with-resources |
지원 대상에서 try/finally로 정리 |
레이블 break·continue |
bool 변수 또는 메서드 분리 |
| 지역 함수 선언 | 클래스의 메서드. 함수 값을 전달할 때는 람다 사용 |
goto, yield, defer |
없음 |