I have been working on Google AdWords and came across this code
adwords-api-6.4.0, com.google.api.adwords.lib.AdWordsUser
public <T extends java.rmi.Remote> T getService(AdWordsService service) throws ServiceException {
try {
return (T) AdWordsServiceFactory.generateSerivceStub(service, this,
开发者_高级运维 service.getEndpointServer(this.isUsingSandbox()), false);
} catch (ClassCastException e) {
throw new ServiceException("Cannot cast serivce. Check the type of return-capture variable.", e);
}
}
which is invoked like this:
AdWordsUser user = new AdWordsUser();
AdGroupServiceInterface adGroupService = user.getService(AdWordsService.V200909.ADGROUP_SERVICE);
Could you please explain how generics work in getService method? How is the return type determined?
What is the purpose of such usage? It doesn't seem like it provides type safety. Does this usage have a specific name (so I could find more info on it and change the question title)?A compiler may often infer the return type from the calling context. In the example provided, the compiler infers that the generic type is AdGroupServiceInterface
because the result is being assigned to that type. If no context is available from which the return type can be inferred, it must be specified explicitly:
user.<AdGroupServiceInterface>getService(svc);
However, the getService
method is not type-safe. Even though it contains a cast, this is only ensuring that the result implements the java.rmi.Remote
interface. Because of type erasure in Java generics, the exact type T
is not known, and the cast can't check to make sure that the result is AdGroupServiceInterface
.
That's why a compiler will warn about the unsafe cast—a ClassCastException
will be raised when the result is assigned to the AdGroupServiceInterface
variable, not inside the method and its catch block.
I know more about C# than Java, but I'd guess that the getService
method takes a parameter of type AdWordsService
, and returns a type T
, which must derive from java.rmi.Remote
.
Presumably the AdWordsServiceFactory.generateSerivceStub
method return type is of type java.rmi.Remote
or similar, so it would be legal to cast this into the T
type.
In C#, generics are used in this way to avoid casting, but the casting's still taking place here. I guess with this particular method, it's saving you from having to cast to your desired type, by making you tell the generic method exactly what type you want back.
I would also imagine that you need to specify the type of T
in your call to getService
. Maybe like this?
AdGroupServiceInterface adGroupService = user.getService<AdGroupServiceInterface>(AdWordsService.V200909.ADGROUP_SERVICE);
精彩评论