DEV Community

Composite
Composite

Posted on

[Java vs .NET] void

2016년 8월 24일 from blog.hazard.kr

Java

void 라는 타입이 있다.
심지어는 Void 클래스까지 있다. java.lang.Void 로.
안타깝게도 Void 클래스를 통해 상속 불가능하며, constructorprivate 라 접근 불가능하다.
그럼 자바는 왜 void를 타입으로 만들었냐, 바로 리플렉션 때문이다.

public class Test {
 public static void main(String[] args) throws SecurityException, NoSuchMethodException {
  Class c1 = Test1.class.getMethod("Testt",null).getReturnType();
  System.out.println(c1 == Void.TYPE);
  System.out.println(c1 == Void.class);
 }
}

class Test1{
 public void Testt(){}
}
Enter fullscreen mode Exit fullscreen mode

여기서 눈여겨볼 부분이 바로 getMethod 에서 메소드 정보를 불러온 다음 getReturnType 메소드를 호출하는데,
만약 void가 키워드로 끝났을 경우 얘가 void인지 아닌지 판가름하기 어려워진다.
이런 디자인으로 인해 자바에서는 Void라는 클래스를 만들었다.
그럼 void는 원시 타입인가? 맞다. 단지 다른 원시 타입처럼 변수 등으로 타입 선언이 안된다는 것 뿐이다. (컴파일러가 막는다)
근데 제네릭은 웃기게 먹힌다. 즉, Future<Void> 가 먹혀서 void 람다식을 쓸 수 있다는 것이다. 오 시발…

.NET

.NET Framework에서도 voidSystem.Void 구조체의 별칭으로, 엄밀히 말하자면 타입은 맞다.
하지만, 자바와는 달리 제네릭으로도조차 못쓴다. MSDN에서는 Void 구조체를 아래와 같이 설명한다.

The Void structure is used in the System.Reflection namespace, but is rarely useful in a typical application. The Void structure has no members other than the ones all types inherit from the Object class.

이 구조체는 리플렉션용 구조체라는 것이다. 그 외에는 쓸 곳도 없고. 자바와 용도는 다를 게 없다.
그렇다면 void 메소드의 리턴타입을 어떻게 가져오나, 자바와 같이 리플렉션을 사용해 보겠다.

public class Test {
 public static void Main(string[] args) {
  Type c1 = typeof(Test1).GetMethod("Testt").ReturnType;
  Console.WriteLine(c1 == typeof(void));
  //Console.WriteLine(c1 == typeof(System.Void)); //CS0673 오류
 }
}

class Test1{
 public void Testt(){}
}
Enter fullscreen mode Exit fullscreen mode

자바와 비슷하다.

근데 희한하게 typeof(System.Void) 식이 안먹힌다. 자바에서 Void.class 식으로 타입 가져올 수 있다는 것과 대조적이다.
게다가 자바와 달리 제네릭을 못쓴다. 이렇게 막힌 이유는 ECMA 335 표준에 따르기 때문인데,
Partition II, Section 9.4 에서 제네릭에서 사용하지 말하야 할 유형을 아래와 같이 기술했다.

참조형 형식 (예: System.Generic.Collection.List 1<string&> 이렇게 하면 안 됨.)
값 형식 중 필드에 CIL 평가 영역(어셈블리 상 평가식)을 가리키는 유형 (예:List<System.RuntimeArgumentHandle>)
void (예: List<System.Void> 이렇게 하면 안 됨.)
즉, 이 표준으로 인해 컴파일러에서 Void 구조체 사용을 아예 막은 것이다. 물론 자바도 닷넷에 비해 느슨하지만 막힌 건 마찬가지이다.
만약 List<System.Void> 이런 식으로 제네릭이나 할당 식으로 사용하려 하면 컴파일러는 아래와 같은 오류를 내뱉을 것이다.

System.Void cannot be used from C# — use typeof(void) to get the void type object
System.Void는 C#에서 사용할 수 없습니다. void 형식 개체를 가져오려면 typeof(void)를 사용하세요.
Enter fullscreen mode Exit fullscreen mode

그러므로 void 타입을 가져오려면 typeof(void) 외에는 방법이 없다.
C/C++ 처럼 void* 포인터도 가질 수 있는데 이 글 범주에서 벗어나고 관련도 없기 때문에 설명은 하지 않겠다.

그렇다. 결론적으로 얘기하면 자바나 닷넷이나 void는 리플렉션용으로 메소드 반환 형식을 인식하기 위해서만 존재하는 타입인 것이다.
끗.

Top comments (0)