- *์ Any?๋ ๋ค๋ฅด๋ค. ์๋๋ฉด, MutableList๋ T์ ๋ํด ๋ฌด๊ณต๋ณ์ด๊ธฐ ๋๋ฌธ.
MutableList<Any?>๋ ๋ชจ๋ ํ์ ์ ์์๋ฅผ ๋ด์ ์ ์์์ ์๋ฏธํ๋ ๋ฐ๋ฉด,
MutableList<*>์ ์ด๋ค ํ์ ์ด๋ผ๋ ๋ค์ด์ฌ ์ ์์ผ๋, ๊ตฌ์ฒด์ ์ธ ํ์ ์ด ๊ฒฐ์ ๋๋ ๊ณผ์ ์ด ์งํ๋๊ณ , ์ผ๋จ ํ์ ์ด ๊ฒฐ์ ๋๋ฉด ๊ทธ ํ์ (๊ณผ ํ์ ํ์ )์ ์์๋ง ๋ด์ ์ ์๋ค. ์ฆ, ๊ตฌ์ฒด์ ์ธ ํ์ ์ด ๊ฒฐ์ ๋๋ค๋ ์ ์ด ์ค์ํ๋ค.
- *์ ์๋ฐ์ ?๋ ๋ค๋ฅด๋ค.
MutableList<*> == MutableList<?>bounded wildcard๋ ์ฌ์ค in/out์ ๋์๋๊ธฐ ๋๋ฌธ์, unbounded๋ง ํํํ๋ค๊ณ ๋ณผ ์ ์๋ค.
interface Function(in T, out U> {
. . .
}
fun foo(bar: Function<*, *>) {
// == bar: Function<in Nothing, out Any?>
}
in์ผ๋ก ์ ์๋์ด ์๋ ์ธ์๋ฅผ *๋ก ๋ฐ์ผ๋ฉด in Nothing์ธ ๊ฒ์ผ๋ก ๊ฐ์ฃผํ๋ค. out์ผ๋ก ์ ์๋์ด ์๋ ์ธ์๋ฅผ *๋ก ๋ฐ์ผ๋ฉด out Any?์ธ ๊ฒ์ผ๋ก ๊ฐ์ฃผํ๋ค. ๊ทธ๋์ *๋ฅผ ์ฌ์ฉํ๋๋ผ๋ ํจ์ ๋ด๋ถ์์ T, U์ ์์น์ ๋ฐ๋ผ ๋ฉ์๋ ํธ์ถ์ด ์ ํ๋ ์ ์๋ค.
class VarianceTest<in T, out U>(conT: T, conU: U) {
// val propT: T = conT
// type parameter T is declared as 'in' but occurs in 'out' position in type T
val propU: U = conU
// fun printAll(t: T, u: U)
// type parameter U is declared as 'out' but occurs in 'in' position in type U
fun printAll(t: T) {
print(t)
}
}
fun starTestFunc(v: VarianceTest<*, *>) {
// v.printAll(1)
// Out-projected type 'VarianceTest<*, *>' prohibits the use of 'public final fun printAll(t: T): Unit defined in VarianceTest'
// type hinting๋ ์์ v.printAll(t: Nothing)์ผ๋ก *์กํ๋ค*.
print(v.propU) // out์ out Any?๊ฐ ๋๋๊น Any?์ ์๋ ๋ฉ์๋๋ฅผ ํธ์ถํ๊ฑฐ๋ ํ๋๊ฑด ์ ๋๋ค.
}
์๋ฐ์์ ?์ T๋ฅผ ๋ชจ๋ ์ฌ์ฉํ ์ ์์ ๋ ์ธ์๋ค๊ณผ ๋ฆฌํดํ์
์ด ์๋ก ๊ด๊ณ๋ฅผ ๋งบ๊ณ ์์ผ๋ฉด T, ์๋๋ฉด ?๋ฅผ ์ฌ์ฉํด์ผ ์กฐ๊ธ ๋ ์๋๊ฐ ๋ช
ํํด์ง๋ ์ฝ๋๊ฐ ๋๋ค
๋ด๋ถ์์ ํ์ ์ ์ด์ฉํ ์์ ์ ํ ๋๋ T๋ฅผ ์ฌ์ฉํ๊ณ ๊ทธ๋ ์ง ์์ผ๋ฉด ?๋ฅผ ์ฌ์ฉํ์ฌ์ผ ํ๋ค ์๋ฅผ๋ค์ด ๋ค์๊ณผ ๊ฐ์ด list์ ๊ธฐ๋ฅ๋ง์ ์ฌ์ฉํ๊ณ list๋ด๋ถ์ ์์๋ฅผ ์ฌ์ฉํ์ง ์๋ ๊ฒฝ์ฐ์๋ ์์ผ๋์นด๋๊ฐ ๋ ๋์ ๋ฐฉ๋ฒ์ด๋ค
// bad
public <T> boolean isEmpty(List<T> list) {
return list.size() == 0;
}
// good
public boolean isEmpty(List<?> list) {
return list.size() == 0;
}https://medium.com/@joongwon/java-java%EC%9D%98-generics-604b562530b3