Однако есть небольшая лазейка: если вы определите свой Foo
класс как абстрактный. Это означало бы, что вам нужно создать экземпляр класса следующим образом:
Foo<MyType> myFoo = new Foo<MyType>(){};
(Обратите внимание на двойные фигурные скобки в конце.)
Теперь вы можете получить тип T
во время выполнения :
Type mySuperclass = myFoo.getClass().getGenericSuperclass();
Type tType = ((ParameterizedType)mySuperclass).getActualTypeArguments()[0];
Обратите внимание, что mySuperclass
должен быть суперклассом определения класса, фактически определяющим конечный тип для T
.
Он также не очень изящный, но вы должны решить, предпочитаете ли вы new Foo<MyType>(){}
или new Foo<MyType>(MyType.class);
в своем коде.
Например:
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.NoSuchElementException;
/**
* Captures and silently ignores stack exceptions upon popping.
*/
public abstract class SilentStack<E> extends ArrayDeque<E> {
public E pop() {
try {
return super.pop();
}
catch( NoSuchElementException nsee ) {
return create();
}
}
public E create() {
try {
Type sooper = getClass().getGenericSuperclass();
Type t = ((ParameterizedType)sooper).getActualTypeArguments()[ 0 ];
return (E)(Class.forName( t.toString() ).newInstance());
}
catch( Exception e ) {
return null;
}
}
}
Затем:
public class Main {
// Note the braces...
private Deque<String> stack = new SilentStack<String>(){};
public static void main( String args[] ) {
// Returns a new instance of String.
String s = stack.pop();
System.out.printf( "s = '%s'\n", s );
}
}
Я считаю, что вы можете сделать это с помощью комбинатора zoom
из Control.Lens.Zoom
:
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
import Control.Monad.State
data SomeState = SomeState { _int :: Int, _string :: String } deriving (Show)
makeLenses ''SomeState
updateInt :: Int -> State Int ()
updateInt x = id .= x
updateString :: String -> State String ()
updateString x = id .= x
updateSomeState :: Int -> State SomeState ()
updateSomeState x = zoom int (updateInt x)
GHCi:
*Main> runStateT (updateSomeState 5) (SomeState 3 "hi")
Identity ((),SomeState {_int = 5, _string = "hi"})