简体   繁体   中英

Explain how generics work in this method

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)?

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);

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM