object T {
def main(args: Array[String]) {
val e = new { var id = 5; var name = "Prashant" }
assert(e.id == 5)
}
}
좋아, 잘 정리 해보자. e
의 유형이 구조 유형 인 스칼라 2.7 및 스칼라 2.8의 리플렉션을 사용합니다. 스칼라가 리플렉션을 통해 처리합니다.
package <empty> {
final class T extends java.lang.Object with ScalaObject {
private <synthetic> <static> var reflMethod$Cache1: java.lang.reflect.Method = null;
private <synthetic> <static> var reflClass$Cache1: java.lang.Class = null;
<synthetic> <static> def reflMethod$Method1(x$1: java.lang.Class): java.lang.reflect.Method = {
if (T.this.reflMethod$Cache1.eq(null).||(T.this.reflClass$Cache1.ne(x$1)))
{
T.this.reflMethod$Cache1 = x$1.getMethod("id", Array[java.lang.Class]{});
T.this.reflClass$Cache1 = x$1;
()
};
T.this.reflMethod$Cache1
};
@remote def $tag(): Int = scala.ScalaObject$class.$tag(T.this);
def main(args: Array[java.lang.String]): Unit = {
val e: java.lang.Object = {
new T$$anon$1()
};
scala.this.Predef.assert(scala.Int.unbox({
var exceptionResult1: java.lang.Object = _;
try {
exceptionResult1 = T.reflMethod$Method1(e.getClass()).invoke(e, Array[java.lang.Object]{})
} catch {
case ($1$ @ (_: java.lang.reflect.InvocationTargetException)) => {
exceptionResult1 = throw $1$.getCause()
}
};
exceptionResult1
}.$asInstanceOf[java.lang.Integer]()).==(5))
};
def this(): object T = {
T.super.this();
()
}
};
final class T$$anon$1 extends java.lang.Object {
private[this] var id: Int = _;
<accessor> def id(): Int = T$$anon$1.this.id;
<accessor> def id_=(x$1: Int): Unit = T$$anon$1.this.id = x$1;
private[this] var name: java.lang.String = _;
<accessor> def name(): java.lang.String = T$$anon$1.this.name;
<accessor> def name_=(x$1: java.lang.String): Unit = T$$anon$1.this.name = x$1;
def this(): T$$anon$1 = {
T$$anon$1.this.id = 5;
T$$anon$1.this.name = "Prashant";
T$$anon$1.super.this();
()
}
}
}
일이 벌어 일부 캐싱이있다,하지만 난 id
과 name
번갈아 경우 이미 캐시를 무효화 것 : 여기 청소 시간 (scalac -Xprint:cleanup
)에서 생성 된 코드입니다. Scala 2.8은 리플렉션 (reflection)과 캐싱 (caches)을 수행하지만 더 효율적인 캐싱 기술을 사용하므로 전반적인 성능이 향상됩니다.
이
val (ID, Name) = (5, "Prashant")
assertEquals(5, ID)
당신은이를 사용할 수 있습니다 같이
package <empty> {
final class T extends java.lang.Object with ScalaObject {
final private <synthetic> <static> var reflParams$Cache1: Array[java.lang.Class] = Array[java.lang.Class]{};
@volatile
private <synthetic> <static> var reflPoly$Cache1: scala.runtime.MethodCache = new scala.runtime.EmptyMethodCache();
<synthetic> <static> def reflMethod$Method1(x$1: java.lang.Class): java.lang.reflect.Method = {
var method1: java.lang.reflect.Method = T.reflPoly$Cache1.find(x$1);
if (method1.ne(null))
return method1
else
{
method1 = x$1.getMethod("id", T.reflParams$Cache1);
T.reflPoly$Cache1 = T.reflPoly$Cache1.add(x$1, method1);
return method1
}
};
def main(args: Array[java.lang.String]): Unit = {
val e: java.lang.Object = {
new T$$anon$1()
};
scala.this.Predef.assert(scala.Int.unbox({
val qual1: java.lang.Object = e;
{
var exceptionResult1: java.lang.Object = _;
try {
exceptionResult1 = T.reflMethod$Method1(qual1.getClass()).invoke(qual1, Array[java.lang.Object]{})
} catch {
case ($1$ @ (_: java.lang.reflect.InvocationTargetException)) => {
exceptionResult1 = throw $1$.getCause()
}
};
exceptionResult1
}.$asInstanceOf[java.lang.Integer]()
}).==(5))
};
def this(): object T = {
T.reflParams$Cache1 = Array[java.lang.Class]{};
T.reflPoly$Cache1 = new scala.runtime.EmptyMethodCache();
T.super.this();
()
}
};
final class T$$anon$1 extends java.lang.Object {
private[this] var id: Int = _;
<accessor> def id(): Int = T$$anon$1.this.id;
<accessor> def id_=(x$1: Int): Unit = T$$anon$1.this.id = x$1;
private[this] var name: java.lang.String = _;
<accessor> def name(): java.lang.String = T$$anon$1.this.name;
<accessor> def name_=(x$1: java.lang.String): Unit = T$$anon$1.this.name = x$1;
def this(): T$$anon$1 = {
T$$anon$1.super.this();
T$$anon$1.this.id = 5;
T$$anon$1.this.name = "Prashant";
()
}
}
}
영리합니다. 이 id와 name 멤버를 가진 새로운 익명 AnyRef 서브 클래스를 생성합니까? – joev
네, 그렇습니다. Scala 2.7, IIRC에서는 리플렉션을 사용하기 때문에 성능이 좋지 않습니다. 확실하지는 않지만 중요한 일이라면 그것을 확인해야합니다. –
그 이유는 모르겠다. 컴파일러는 (익명) 클래스 정의에 액세스 할 수 있으므로 리플렉션을 할 필요가 없습니다. 구조적 타이핑 만이 내가 아는 한 반사의 사용을 수반합니다. –