1. 程式人生 > >關於反射裡的內部類和外部類

關於反射裡的內部類和外部類

    最近寫適配,遇到了一點小問題,

1.通過反射得到某個例項,可是這個例項是內部類,想要得到並通過invoke方法執行外部類的方法,需要得到外部類的例項,通過網上查閱,每一個內部類都有一個this$0的變數是指向外部類的引用,通過getdeclearedField得到這個引用,然後setaccessible(true)得到訪問許可權例項化外部類就得到了,此時這個內部類的例項對應的外部類的例項了。

      可是我這裡的內部類是static的,上面的this$0是有限制的,靜態內部類和靜態方法裡面的內部類是沒有this$0這個引用的,因為靜態內部類,是面向類的而不是物件,能夠獨自的應用本身,而脫離外部類,和外部類沒有這個引用關係。

2.     還有一個方法是要invoke的方法在內部類,得到的例項是外部類,想得到對應的內部類的例項,並沒有這層關係。所以這個方法不可行

在這裡記錄下通過外部類得到內部類的方法:

clazz.getDeclaredClasses();

通過內部類得到外部類的方法:

Clazz.getDeclaringClass();

得到類的建構函式

clazz.getConstructors()

得到類的所有建構函式

clazz.getDeclaredConstructor();

注意:建構函式通過getmethod是得不到的!只能通過getdeclaredconstructor/getconstructors得到

最後解決的辦法,在前輩的幫助下,發現setheader方法,最終是走的內部類的request裡面的add方法這樣就不需要關聯內部類和外部類了。下面是asynchttpclient一個類的程式碼:

package com.ning.http.client;

import com.ning.http.client.cookie.Cookie;

import com.ning.http.client.multipart.Part;

import com.ning.http.client.uri.Uri;

import com.ning.http.util.AsyncHttpProviderUtils;

import com.ning.http.util.MiscUtils;

import com.ning.http.util.UriEncoder;

import java.io.File;

import java.io.InputStream;

import java.net.InetAddress;

import java.util.ArrayList;

import java.util.Collection;

import java.util.Collections;

import java.util.List;

import java.util.Map;

import java.util.Map.Entry;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

public abstract class RequestBuilderBase<T extends RequestBuilderBase<T>>

{

  private static final Logger logger = LoggerFactory.getLogger(RequestBuilderBase.class);

  private static final Uri DEFAULT_REQUEST_URL = Uri.create("http://localhost");

  private final Class<T> derived;

  protected final RequestImpl request;

  protected UriEncoder uriEncoder;

  protected List<Param> rbQueryParams;

  protected SignatureCalculator signatureCalculator;

  private static final class RequestImpl

    implements Request

  {

    private String method;

    private Uri uri;

    private InetAddress address;

    private InetAddress localAddress;

    private FluentCaseInsensitiveStringsMap headers = new FluentCaseInsensitiveStringsMap();

    private ArrayList<Cookie> cookies;

    private byte[] byteData;

    private List<byte[]> compositeByteData;

    private String stringData;

    private InputStream streamData;

    private BodyGenerator bodyGenerator;

    private List<Param> formParams;

    private List<Part> parts;

    private String virtualHost;

    private long length = -1L;

    public ProxyServer proxyServer;

    private Realm realm;

    private File file;

    private Boolean followRedirects;

    private int requestTimeout;

    private long rangeOffset;

    public String charset;

    private ConnectionPoolPartitioning connectionPoolPartitioning = ConnectionPoolPartitioning.PerHostConnectionPoolPartitioning.INSTANCE;

    private NameResolver nameResolver = NameResolver.JdkNameResolver.INSTANCE;

    private List<Param> queryParams;

    public RequestImpl() {}

    public RequestImpl(Request prototype)

    {

      if (prototype != null)

      {

        this.method = prototype.getMethod();

        this.uri = prototype.getUri();

        this.address = prototype.getInetAddress();

        this.localAddress = prototype.getLocalAddress();

        this.headers = new FluentCaseInsensitiveStringsMap(prototype.getHeaders());

        this.cookies = new ArrayList(prototype.getCookies());

        this.byteData = prototype.getByteData();

        this.compositeByteData = prototype.getCompositeByteData();

        this.stringData = prototype.getStringData();

        this.streamData = prototype.getStreamData();

        this.bodyGenerator = prototype.getBodyGenerator();

        this.formParams = (prototype.getFormParams() == null ? null : new ArrayList(prototype.getFormParams()));

        this.parts = (prototype.getParts() == null ? null : new ArrayList(prototype.getParts()));

        this.virtualHost = prototype.getVirtualHost();

        this.length = prototype.getContentLength();

        this.proxyServer = prototype.getProxyServer();

        this.realm = prototype.getRealm();

        this.file = prototype.getFile();

        this.followRedirects = prototype.getFollowRedirect();

        this.requestTimeout = prototype.getRequestTimeout();

        this.rangeOffset = prototype.getRangeOffset();

        this.charset = prototype.getBodyEncoding();

        this.connectionPoolPartitioning = prototype.getConnectionPoolPartitioning();

        this.nameResolver = prototype.getNameResolver();

      }

    }

    public String getMethod()

    {

      return this.method;

    }

    public InetAddress getInetAddress()

    {

      return this.address;

    }

    public InetAddress getLocalAddress()

    {

      return this.localAddress;

    }

    public Uri getUri()

    {

      return this.uri;

    }

    public String getUrl()

    {

      return this.uri.toUrl();

    }

    public FluentCaseInsensitiveStringsMap getHeaders()

    {

      return this.headers;

    }

    public Collection<Cookie> getCookies()

    {

      return this.cookies != null ? Collections.unmodifiableCollection(this.cookies) : Collections.emptyList();

    }

    public byte[] getByteData()

    {

      return this.byteData;

    }

    public List<byte[]> getCompositeByteData()

    {

      return this.compositeByteData;

    }

    public String getStringData()

    {

      return this.stringData;

    }

    public InputStream getStreamData()

    {

      return this.streamData;

    }

    public BodyGenerator getBodyGenerator()

    {

      return this.bodyGenerator;

    }

    public long getContentLength()

    {

      return this.length;

    }

    public List<Param> getFormParams()

    {

      return this.formParams != null ? this.formParams : Collections.emptyList();

    }

    public List<Part> getParts()

    {

      return this.parts != null ? this.parts : Collections.emptyList();

    }

    public String getVirtualHost()

    {

      return this.virtualHost;

    }

    public ProxyServer getProxyServer()

    {

      return this.proxyServer;

    }

    public Realm getRealm()

    {

      return this.realm;

    }

    public File getFile()

    {

      return this.file;

    }

    public Boolean getFollowRedirect()

    {

      return this.followRedirects;

    }

    public int getRequestTimeout()

    {

      return this.requestTimeout;

    }

    public long getRangeOffset()

    {

      return this.rangeOffset;

    }

    public String getBodyEncoding()

    {

      return this.charset;

    }

    public ConnectionPoolPartitioning getConnectionPoolPartitioning()

    {

      return this.connectionPoolPartitioning;

    }

    public NameResolver getNameResolver()

    {

      return this.nameResolver;

    }

    public List<Param> getQueryParams()

    {

      if (this.queryParams == null) {

        if (MiscUtils.isNonEmpty(this.uri.getQuery()))

        {

          this.queryParams = new ArrayList(1);

          for (String queryStringParam : this.uri.getQuery().split("&"))

          {

            int pos = queryStringParam.indexOf('=');

            if (pos <= 0) {

              this.queryParams.add(new Param(queryStringParam, null));

            } else {

              this.queryParams.add(new Param(queryStringParam.substring(0, pos), queryStringParam.substring(pos + 1)));

            }

          }

        }

        else

        {

          this.queryParams = Collections.emptyList();

        }

      }

      return this.queryParams;

    }

    public String toString()

    {

      StringBuilder sb = new StringBuilder(getUrl());

      sb.append("\t");

      sb.append(this.method);

      sb.append("\theaders:");

      if (MiscUtils.isNonEmpty(this.headers)) {

        for (String name : this.headers.keySet())

        {

          sb.append("\t");

          sb.append(name);

          sb.append(":");

          sb.append(this.headers.getJoinedValue(name, ", "));

        }

      }

      if (MiscUtils.isNonEmpty(this.formParams))

      {

        sb.append("\tformParams:");

        for (Param param : this.formParams)

        {

          sb.append("\t");

          sb.append(param.getName());

          sb.append(":");

          sb.append(param.getValue());

        }

      }

      return sb.toString();

    }

  }

  protected RequestBuilderBase(Class<T> derived, String method, boolean disableUrlEncoding)

  {

    this(derived, method, UriEncoder.uriEncoder(disableUrlEncoding));

  }

  protected RequestBuilderBase(Class<T> derived, String method, UriEncoder uriEncoder)

  {

    this.derived = derived;

    this.request = new RequestImpl();

    this.request.method = method;

    this.uriEncoder = uriEncoder;

  }

  protected RequestBuilderBase(Class<T> derived, Request prototype)

  {

    this(derived, prototype, UriEncoder.FIXING);

  }

  protected RequestBuilderBase(Class<T> derived, Request prototype, UriEncoder uriEncoder)

  {

    this.derived = derived;

    this.request = new RequestImpl(prototype);

    this.uriEncoder = uriEncoder;

  }

  public T setUrl(String url)

  {

    return setUri(Uri.create(url));

  }

  public T setUri(Uri uri)

  {

    this.request.uri = uri;

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T setInetAddress(InetAddress address)

  {

    this.request.address = address;

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T setLocalInetAddress(InetAddress address)

  {

    this.request.localAddress = address;

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T setVirtualHost(String virtualHost)

  {

    this.request.virtualHost = virtualHost;

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T setHeader(String name, String value)

  {

    this.request.headers.replaceWith(name, new String[] { value });

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T addHeader(String name, String value)

  {

    if (value == null)

    {

      logger.warn("Value was null, set to \"\"");

      value = "";

    }

    this.request.headers.add(name, value);

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T setHeaders(FluentCaseInsensitiveStringsMap headers)

  {

    this.request.headers = (headers == null ? new FluentCaseInsensitiveStringsMap() : new FluentCaseInsensitiveStringsMap(headers));

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T setHeaders(Map<String, Collection<String>> headers)

  {

    this.request.headers = (headers == null ? new FluentCaseInsensitiveStringsMap() : new FluentCaseInsensitiveStringsMap(headers));

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T setContentLength(int length)

  {

    this.request.length = length;

    return (RequestBuilderBase)this.derived.cast(this);

  }

  private void lazyInitCookies()

  {

    if (this.request.cookies == null) {

      this.request.cookies = new ArrayList(3);

    }

  }

  public T setCookies(Collection<Cookie> cookies)

  {

    this.request.cookies = new ArrayList(cookies);

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T addCookie(Cookie cookie)

  {

    lazyInitCookies();

    this.request.cookies.add(cookie);

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T addOrReplaceCookie(Cookie cookie)

  {

    String cookieKey = cookie.getName();

    boolean replace = false;

    int index = 0;

    lazyInitCookies();

    for (Cookie c : this.request.cookies)

    {

      if (c.getName().equals(cookieKey))

      {

        replace = true;

        break;

      }

      index++;

    }

    if (replace) {

      this.request.cookies.set(index, cookie);

    } else {

      this.request.cookies.add(cookie);

    }

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public void resetCookies()

  {

    if (this.request.cookies != null) {

      this.request.cookies.clear();

    }

  }

  public void resetQuery()

  {

    this.rbQueryParams = null;

    this.request.uri = this.request.uri.withNewQuery(null);

  }

  public void resetFormParams()

  {

    this.request.formParams = null;

  }

  public void resetNonMultipartData()

  {

    this.request.byteData = null;

    this.request.compositeByteData = null;

    this.request.stringData = null;

    this.request.streamData = null;

    this.request.bodyGenerator = null;

    this.request.length = -1L;

  }

  public void resetMultipartData()

  {

    this.request.parts = null;

  }

  public T setBody(File file)

  {

    this.request.file = file;

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T setBody(byte[] data)

  {

    resetFormParams();

    resetNonMultipartData();

    resetMultipartData();

    this.request.byteData = data;

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T setBody(List<byte[]> data)

  {

    resetFormParams();

    resetNonMultipartData();

    resetMultipartData();

    this.request.compositeByteData = data;

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T setBody(String data)

  {

    resetFormParams();

    resetNonMultipartData();

    resetMultipartData();

    this.request.stringData = data;

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T setBody(InputStream stream)

  {

    resetFormParams();

    resetNonMultipartData();

    resetMultipartData();

    this.request.streamData = stream;

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T setBody(BodyGenerator bodyGenerator)

  {

    this.request.bodyGenerator = bodyGenerator;

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T addQueryParam(String name, String value)

  {

    if (this.rbQueryParams == null) {

      this.rbQueryParams = new ArrayList(1);

    }

    this.rbQueryParams.add(new Param(name, value));

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T addQueryParams(List<Param> params)

  {

    if (this.rbQueryParams == null) {

      this.rbQueryParams = params;

    } else {

      this.rbQueryParams.addAll(params);

    }

    return (RequestBuilderBase)this.derived.cast(this);

  }

  private List<Param> map2ParamList(Map<String, List<String>> map)

  {

    if (map == null) {

      return null;

    }

    List<Param> params = new ArrayList(map.size());

    for (Map.Entry<String, List<String>> entries : map.entrySet())

    {

      name = (String)entries.getKey();

      for (String value : (List)entries.getValue()) {

        params.add(new Param(name, value));

      }

    }

    String name;

    return params;

  }

  public T setQueryParams(Map<String, List<String>> map)

  {

    return setQueryParams(map2ParamList(map));

  }

  public T setQueryParams(List<Param> params)

  {

    if (MiscUtils.isNonEmpty(this.request.uri.getQuery())) {

      this.request.uri = this.request.uri.withNewQuery(null);

    }

    this.rbQueryParams = params;

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T addFormParam(String name, String value)

  {

    resetNonMultipartData();

    resetMultipartData();

    if (this.request.formParams == null) {

      this.request.formParams = new ArrayList(1);

    }

    this.request.formParams.add(new Param(name, value));

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T setFormParams(Map<String, List<String>> map)

  {

    return setFormParams(map2ParamList(map));

  }

  public T setFormParams(List<Param> params)

  {

    resetNonMultipartData();

    resetMultipartData();

    this.request.formParams = params;

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T addBodyPart(Part part)

  {

    resetFormParams();

    resetNonMultipartData();

    if (this.request.parts == null) {

      this.request.parts = new ArrayList();

    }

    this.request.parts.add(part);

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T setProxyServer(ProxyServer proxyServer)

  {

    this.request.proxyServer = proxyServer;

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T setRealm(Realm realm)

  {

    this.request.realm = realm;

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T setFollowRedirects(boolean followRedirects)

  {

    this.request.followRedirects = Boolean.valueOf(followRedirects);

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T setRequestTimeout(int requestTimeout)

  {

    this.request.requestTimeout = requestTimeout;

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T setRangeOffset(long rangeOffset)

  {

    this.request.rangeOffset = rangeOffset;

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T setMethod(String method)

  {

    this.request.method = method;

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T setBodyEncoding(String charset)

  {

    this.request.charset = charset;

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T setConnectionPoolKeyStrategy(ConnectionPoolPartitioning connectionPoolKeyStrategy)

  {

    this.request.connectionPoolPartitioning = connectionPoolKeyStrategy;

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T setNameResolver(NameResolver nameResolver)

  {

    this.request.nameResolver = nameResolver;

    return (RequestBuilderBase)this.derived.cast(this);

  }

  public T setSignatureCalculator(SignatureCalculator signatureCalculator)

  {

    this.signatureCalculator = signatureCalculator;

    return (RequestBuilderBase)this.derived.cast(this);

  }

  private void executeSignatureCalculator()

  {

    if (this.signatureCalculator != null)

    {

      RequestBuilder rb = (RequestBuilder)new RequestBuilder(this.request).setSignatureCalculator(null);

      rb.rbQueryParams = this.rbQueryParams;

      Request unsignedRequest = rb.build();

      this.signatureCalculator.calculateAndAddSignature(unsignedRequest, this);

    }

  }

  private void computeRequestCharset()

  {

    if (this.request.charset == null) {

      try

      {

        String contentType = this.request.headers.getFirstValue("Content-Type");

        if (contentType != null)

        {

          String charset = AsyncHttpProviderUtils.parseCharset(contentType);

          if (charset != null) {

            this.request.charset = charset;

          }

        }

      }

      catch (Throwable localThrowable) {}

    }

  }

  private void computeRequestLength()

  {

    if ((this.request.length < 0L) && (this.request.streamData == null))

    {

      String contentLength = this.request.headers.getFirstValue("Content-Length");

      if (contentLength != null) {

        try

        {

          this.request.length = Long.parseLong(contentLength);

        }

        catch (NumberFormatException localNumberFormatException) {}

      }

    }

  }

  private void validateSupportedScheme(Uri uri)

  {

    String scheme = uri.getScheme();

    if ((scheme == null) || ((!scheme.equalsIgnoreCase("http")) && (!scheme.equalsIgnoreCase("https")) && (!scheme.equalsIgnoreCase("ws")) && 

      (!scheme.equalsIgnoreCase("wss")))) {

      throw new IllegalArgumentException("The URI scheme, of the URI " + uri + ", must be equal (ignoring case) to 'http', 'https', 'ws', or 'wss'");

    }

  }

  private void computeFinalUri()

  {

    if (this.request.uri == null)

    {

      logger.debug("setUrl hasn't been invoked. Using {}", DEFAULT_REQUEST_URL);

      this.request.uri = DEFAULT_REQUEST_URL;

    }

    else

    {

      validateSupportedScheme(this.request.uri);

    }

    this.request.uri = this.uriEncoder.encode(this.request.uri, this.rbQueryParams);

  }

  public Request build()

  {

    executeSignatureCalculator();

    computeFinalUri();

    computeRequestCharset();

    computeRequestLength();

    return this.request;

  }

}