当前位置: 首页>>代码示例>>Java>>正文


Java MethodType.returnType方法代码示例

本文整理汇总了Java中java.lang.invoke.MethodType.returnType方法的典型用法代码示例。如果您正苦于以下问题:Java MethodType.returnType方法的具体用法?Java MethodType.returnType怎么用?Java MethodType.returnType使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在java.lang.invoke.MethodType的用法示例。


在下文中一共展示了MethodType.returnType方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Java代码示例。

示例1: cast

import java.lang.invoke.MethodType; //导入方法依赖的package包/类
/** Forces a cast to class A for target (only if types differ) */
public static MethodHandle cast(Class<?> classA, MethodHandle target) {
    MethodType newType = MethodType.methodType(classA).unwrap();
    MethodType targetType = MethodType.methodType(target.type().returnType()).unwrap();
    
    // don't do a conversion if types are the same. explicitCastArguments has this opto,
    // but we do it explicitly, to make the boolean check simpler
    if (newType.returnType() == targetType.returnType()) {
        return target;
    }
    
    // we don't allow the to/from boolean conversions of explicitCastArguments
    if (newType.returnType() == boolean.class || targetType.returnType() == boolean.class) {
        throw new ClassCastException("Cannot cast " + targetType.returnType() + " to " + newType.returnType());
    }
    
    // null return values are not possible for our arguments.
    return MethodHandles.explicitCastArguments(target, target.type().changeReturnType(newType.returnType()));
}
 
开发者ID:justor,项目名称:elasticsearch_my,代码行数:20,代码来源:DefMath.java

示例2: setTarget

import java.lang.invoke.MethodType; //导入方法依赖的package包/类
@Override
public void setTarget(final MethodHandle newTarget) {
    final MethodType type   = type();
    final boolean    isVoid = type.returnType() == void.class;

    MethodHandle methodHandle = MH.filterArguments(newTarget, 0, MH.bindTo(PROFILEENTRY, this));

    if (isVoid) {
        methodHandle = MH.filterReturnValue(methodHandle, MH.bindTo(PROFILEVOIDEXIT, this));
    } else {
        final MethodType filter = MH.type(type.returnType(), type.returnType());
        methodHandle = MH.filterReturnValue(methodHandle, MH.asType(MH.bindTo(PROFILEEXIT, this), filter));
    }

    super.setTarget(methodHandle);
}
 
开发者ID:SunburstApps,项目名称:OpenJSharp,代码行数:17,代码来源:LinkerCallSite.java

示例3: findFastGetIndexMethod

import java.lang.invoke.MethodType; //导入方法依赖的package包/类
/**
 * Return a fast linked array getter, or null if we have to dispatch to super class
 * @param desc     descriptor
 * @param request  link request
 * @return invocation or null if needs to be sent to slow relink
 */
@Override
public GuardedInvocation findFastGetIndexMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request) {
    final MethodType callType   = desc.getMethodType();
    final Class<?>   indexType  = callType.parameterType(1);
    final Class<?>   returnType = callType.returnType();

    if (ContinuousArrayData.class.isAssignableFrom(clazz) && indexType == int.class) {
        final Object[] args  = request.getArguments();
        final int      index = (int)args[args.length - 1];

        if (has(index)) {
            final MethodHandle getArray     = ScriptObject.GET_ARRAY.methodHandle();
            final int          programPoint = NashornCallSiteDescriptor.isOptimistic(desc) ? NashornCallSiteDescriptor.getProgramPoint(desc) : INVALID_PROGRAM_POINT;
            MethodHandle       getElement   = getElementGetter(returnType, programPoint);
            if (getElement != null) {
                getElement = MH.filterArguments(getElement, 0, MH.asType(getArray, getArray.type().changeReturnType(clazz)));
                final MethodHandle guard = MH.insertArguments(FAST_ACCESS_GUARD, 0, clazz);
                return new GuardedInvocation(getElement, guard, (SwitchPoint)null, ClassCastException.class);
            }
        }
    }

    return null;
}
 
开发者ID:SunburstApps,项目名称:OpenJSharp,代码行数:31,代码来源:ContinuousArrayData.java

示例4: findGetIndexMethod

import java.lang.invoke.MethodType; //导入方法依赖的package包/类
/**
 * Find the appropriate GETINDEX method for an invoke dynamic call.
 *
 * @param desc    the call site descriptor
 * @param request the link request
 *
 * @return GuardedInvocation to be invoked at call site.
 */
protected GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) {
    final MethodType callType                = desc.getMethodType();
    final Class<?>   returnType              = callType.returnType();
    final Class<?>   returnClass             = returnType.isPrimitive() ? returnType : Object.class;
    final Class<?>   keyClass                = callType.parameterType(1);
    final boolean    explicitInstanceOfCheck = explicitInstanceOfCheck(desc, request);

    final String name;
    if (returnClass.isPrimitive()) {
        //turn e.g. get with a double into getDouble
        final String returnTypeName = returnClass.getName();
        name = "get" + Character.toUpperCase(returnTypeName.charAt(0)) + returnTypeName.substring(1, returnTypeName.length());
    } else {
        name = "get";
    }

    final MethodHandle mh = findGetIndexMethodHandle(returnClass, name, keyClass, desc);
    return new GuardedInvocation(mh, getScriptObjectGuard(callType, explicitInstanceOfCheck), (SwitchPoint)null, explicitInstanceOfCheck ? null : ClassCastException.class);
}
 
开发者ID:AdoptOpenJDK,项目名称:openjdk-jdk10,代码行数:28,代码来源:ScriptObject.java

示例5: setTarget

import java.lang.invoke.MethodType; //导入方法依赖的package包/类
@Override
public void setTarget(final MethodHandle newTarget) {
    if (!getNashornDescriptor().isTraceEnterExit()) {
        super.setTarget(newTarget);
        return;
    }

    final MethodType type = type();
    final boolean isVoid = type.returnType() == void.class;

    MethodHandle traceMethodHandle = isVoid ? TRACEVOID : TRACEOBJECT;
    traceMethodHandle = MH.bindTo(traceMethodHandle, this);
    traceMethodHandle = MH.bindTo(traceMethodHandle, newTarget);
    traceMethodHandle = MH.asCollector(traceMethodHandle, Object[].class, type.parameterCount());
    traceMethodHandle = MH.asType(traceMethodHandle, type);

    super.setTarget(traceMethodHandle);
}
 
开发者ID:AdoptOpenJDK,项目名称:openjdk-jdk10,代码行数:19,代码来源:LinkerCallSite.java

示例6: adapt

import java.lang.invoke.MethodType; //导入方法依赖的package包/类
/** 
 * If the interface expects a primitive type to be returned, we can't return Object,
 * But we can set SAM to the wrapper version, and a cast will take place 
 */
private MethodType adapt(MethodType expected, MethodType actual) {
    // add some checks, now that we've set everything up, to deliver exceptions as early as possible.
    if (expected.parameterCount() != actual.parameterCount()) {
        throw new IllegalArgumentException("Incorrect number of parameters for [" + invokedName + 
                                           "] in [" + invokedType.returnType() + "]");
    }
    if (expected.returnType().isPrimitive() && actual.returnType() == Object.class) {
        actual = actual.changeReturnType(MethodType.methodType(expected.returnType()).wrap().returnType());
    }
    return actual;
}
 
开发者ID:justor,项目名称:elasticsearch_my,代码行数:16,代码来源:FunctionRef.java

示例7: createImpl

import java.lang.invoke.MethodType; //导入方法依赖的package包/类
static TupleHandle createImpl(Form form, MethodType type) {
  if (type.returnType() != void.class) {
    throw new IllegalArgumentException();
  }
  TupleHandle handle = FORM_CACHE.get(form);
  if (handle == null) {
    handle = TupleGenerator.generate(form);
    FORM_CACHE.putIfAbsent(form, handle);
  }
  return handle.adapt(type, form);
}
 
开发者ID:forax,项目名称:mjolnir,代码行数:12,代码来源:TupleHandle.java

示例8: of

import java.lang.invoke.MethodType; //导入方法依赖的package包/类
public static Form of(MethodType methodType) {
  if (methodType.returnType() != void.class) {
    throw new IllegalArgumentException();
  }
  return methodType.parameterList().stream()
      .reduce(new Form(0, 0), Form::accumulate, (_1, _2) -> { throw new AssertionError(); });
}
 
开发者ID:forax,项目名称:mjolnir,代码行数:8,代码来源:TupleHandle.java

示例9: filterOptimisticReturnValue

import java.lang.invoke.MethodType; //导入方法依赖的package包/类
/**
 * Given a method handle and an expected return type, perform return value filtering
 * according to the optimistic type coercion rules
 * @param mh method handle
 * @param expectedReturnType expected return type
 * @param programPoint program point
 * @return filtered method
 */
public static MethodHandle filterOptimisticReturnValue(final MethodHandle mh, final Class<?> expectedReturnType, final int programPoint) {
    if(!isValid(programPoint)) {
        return mh;
    }

    final MethodType type = mh.type();
    final Class<?> actualReturnType = type.returnType();
    if(TypeUtilities.isConvertibleWithoutLoss(actualReturnType, expectedReturnType)) {
        return mh;
    }

    final MethodHandle guard = getOptimisticTypeGuard(expectedReturnType, actualReturnType);
    return guard == null ? mh : MH.filterReturnValue(mh, MH.insertArguments(guard, guard.type().parameterCount() - 1, programPoint));
}
 
开发者ID:SunburstApps,项目名称:OpenJSharp,代码行数:23,代码来源:OptimisticReturnFilters.java

示例10: testMultipleArgs

import java.lang.invoke.MethodType; //导入方法依赖的package包/类
/**
 * Tests that MHs.eCA method works correctly with MHs with multiple arguments.
 * @throws Throwable
 */
public static void testMultipleArgs() throws Throwable {
    int arity = 1 + RNG.nextInt(Helper.MAX_ARITY / 2 - 2);
    int arityMinus = RNG.nextInt(arity);
    int arityPlus = arity + RNG.nextInt(Helper.MAX_ARITY / 2 - arity) + 1;
    MethodType mType = Helper.randomMethodTypeGenerator(arity);
    MethodType mTypeNew = Helper.randomMethodTypeGenerator(arity);
    MethodType mTypeNewMinus = Helper.randomMethodTypeGenerator(arityMinus);
    MethodType mTypeNewPlus = Helper.randomMethodTypeGenerator(arityPlus);
    Class<?> rType = mType.returnType();
    MethodHandle original;
    if (rType.equals(void.class)) {
        MethodType mt = MethodType.methodType(void.class);
        original = MethodHandles.publicLookup()
                .findStatic(THIS_CLASS, "retVoid", mt);
    } else {
        Object rValue = Helper.castToWrapper(1, rType);
        original = MethodHandles.constant(rType, rValue);
    }
    original = Helper.addTrailingArgs(original, arity, mType.parameterList());
    MethodHandle target = MethodHandles
                .explicitCastArguments(original, mTypeNew);
    Object[] parList = Helper.randomArgs(mTypeNew.parameterList());
    for (int i = 0; i < parList.length; i++) {
        if (parList[i] instanceof String) {
            parList[i] = null; //getting rid of Stings produced by randomArgs
        }
    }
    target.invokeWithArguments(parList);
    checkForWrongMethodTypeException(original, mTypeNewMinus);
    checkForWrongMethodTypeException(original, mTypeNewPlus);
}
 
开发者ID:lambdalab-mirror,项目名称:jdk8u-jdk,代码行数:36,代码来源:ExplicitCastArgumentsTest.java

示例11: testReturnType

import java.lang.invoke.MethodType; //导入方法依赖的package包/类
/**
 * Test of returnType method, of class MethodType.
 */
@Test
public void testReturnType() {
    System.out.println("returnType");
    MethodType instance = mt_viS;
    Class<?> expResult = void.class;
    Class<?> result = instance.returnType();
    assertSame(expResult, result);
}
 
开发者ID:lambdalab-mirror,项目名称:jdk8u-jdk,代码行数:12,代码来源:MethodTypeTest.java

示例12: testCountedLoopBodyParameters

import java.lang.invoke.MethodType; //导入方法依赖的package包/类
@Test(dataProvider = "countedLoopBodyParameters")
public static void testCountedLoopBodyParameters(MethodType countType, MethodType initType, MethodType bodyType) throws Throwable {
    MethodHandle loop = MethodHandles.countedLoop(
            MethodHandles.empty(countType),
            initType == null ? null : MethodHandles.empty(initType),
            MethodHandles.empty(bodyType));
    // The rule:  If body takes the minimum number of parameters, then take what countType offers.
    // The initType has to just roll with whatever the other two agree on.
    int innerParams = (bodyType.returnType() == void.class ? 1 : 2);
    MethodType expectType = bodyType.dropParameterTypes(0, innerParams);
    if (expectType.parameterCount() == 0)
        expectType = expectType.insertParameterTypes(0, countType.parameterList());
    assertEquals(expectType, loop.type());
}
 
开发者ID:AdoptOpenJDK,项目名称:openjdk-jdk10,代码行数:15,代码来源:LoopCombinatorTest.java

示例13: getUnnamedPropertySetter

import java.lang.invoke.MethodType; //导入方法依赖的package包/类
private GuardedInvocationComponent getUnnamedPropertySetter(final ComponentLinkRequest req) throws Exception {
    final CallSiteDescriptor callSiteDescriptor = req.getDescriptor();
    // Must have three arguments: target object, property name, and property value.
    assertParameterCount(callSiteDescriptor, 3);

    // We want setters that conform to "Object(O, V)". Note, we aren't doing "R(O, V)" as it might not be
    // valid for us to convert return values proactively. Also, since we don't know what setters will be
    // invoked, we'll conservatively presume Object return type. The one exception is void return.
    final MethodType origType = callSiteDescriptor.getMethodType();
    final MethodType type = origType.returnType() == void.class ? origType : origType.changeReturnType(Object.class);
    final LinkerServices linkerServices = req.linkerServices;

    // What's below is basically:
    //   foldArguments(guardWithTest(isNotNull, invoke, null|nextComponent.invocation),
    //     get_setter_handle(type, linkerServices))
    // only with a bunch of method signature adjustments. Basically, retrieve method setter
    // MethodHandle; if it is non-null, invoke it, otherwise either return null, or delegate to next
    // component's invocation.

    // Call site type is "ret_type(object_type,property_name_type,property_value_type)", which we'll
    // abbreviate to R(O, N, V) going forward, although we don't really use R here (see above about using
    // Object return type).
    final MethodType setterType = type.dropParameterTypes(1, 2);
    // Bind property setter handle to the expected setter type and linker services. Type is
    // MethodHandle(Object, String, Object)
    final MethodHandle boundGetter = MethodHandles.insertArguments(getPropertySetterHandle, 0,
            callSiteDescriptor.changeMethodType(setterType), linkerServices);

    // Cast getter to MethodHandle(O, N, V)
    final MethodHandle typedGetter = linkerServices.asType(boundGetter, type.changeReturnType(
            MethodHandle.class));

    // Handle to invoke the setter R(MethodHandle, O, V)
    final MethodHandle invokeHandle = MethodHandles.exactInvoker(setterType);
    // Handle to invoke the setter, dropping unnecessary fold arguments R(MethodHandle, O, N, V)
    final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandle, 2, type.parameterType(
            1));
    final GuardedInvocationComponent nextComponent = getNextComponent(req);

    final MethodHandle fallbackFolded;
    if (nextComponent == null) {
        // Object(MethodHandle)->Object(MethodHandle, O, N, V); returns constant null
        fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_METHOD_HANDLE, 1,
                type.parameterList()).asType(type.insertParameterTypes(0, MethodHandle.class));
    } else {
        // Object(O, N, V)->Object(MethodHandle, O, N, V); adapts the next component's invocation to drop the
        // extra argument resulting from fold
        fallbackFolded = MethodHandles.dropArguments(nextComponent.getGuardedInvocation().getInvocation(),
                0, MethodHandle.class);
    }

    // fold(R(MethodHandle, O, N, V), MethodHandle(O, N, V))
    final MethodHandle compositeSetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
                IS_METHOD_HANDLE_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter);
    if(nextComponent == null) {
        return getClassGuardedInvocationComponent(compositeSetter, type);
    }
    return nextComponent.compose(compositeSetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
}
 
开发者ID:AdoptOpenJDK,项目名称:openjdk-jdk10,代码行数:60,代码来源:AbstractJavaLinker.java

示例14: getPropertySetter

import java.lang.invoke.MethodType; //导入方法依赖的package包/类
private GuardedInvocationComponent getPropertySetter(final CallSiteDescriptor callSiteDescriptor,
        final LinkerServices linkerServices, final List<String> operations) throws Exception {
    switch(callSiteDescriptor.getNameTokenCount()) {
        case 2: {
            // Must have three arguments: target object, property name, and property value.
            assertParameterCount(callSiteDescriptor, 3);

            // We want setters that conform to "Object(O, V)". Note, we aren't doing "R(O, V)" as it might not be
            // valid for us to convert return values proactively. Also, since we don't know what setters will be
            // invoked, we'll conservatively presume Object return type. The one exception is void return.
            final MethodType origType = callSiteDescriptor.getMethodType();
            final MethodType type = origType.returnType() == void.class ? origType : origType.changeReturnType(Object.class);

            // What's below is basically:
            //   foldArguments(guardWithTest(isNotNull, invoke, null|nextComponent.invocation),
            //     get_setter_handle(type, linkerServices))
            // only with a bunch of method signature adjustments. Basically, retrieve method setter
            // MethodHandle; if it is non-null, invoke it, otherwise either return null, or delegate to next
            // component's invocation.

            // Call site type is "ret_type(object_type,property_name_type,property_value_type)", which we'll
            // abbreviate to R(O, N, V) going forward, although we don't really use R here (see above about using
            // Object return type).
            final MethodType setterType = type.dropParameterTypes(1, 2);
            // Bind property setter handle to the expected setter type and linker services. Type is
            // MethodHandle(Object, String, Object)
            final MethodHandle boundGetter = MethodHandles.insertArguments(getPropertySetterHandle, 0,
                    callSiteDescriptor.changeMethodType(setterType), linkerServices);

            // Cast getter to MethodHandle(O, N, V)
            final MethodHandle typedGetter = linkerServices.asType(boundGetter, type.changeReturnType(
                    MethodHandle.class));

            // Handle to invoke the setter R(MethodHandle, O, V)
            final MethodHandle invokeHandle = MethodHandles.exactInvoker(setterType);
            // Handle to invoke the setter, dropping unnecessary fold arguments R(MethodHandle, O, N, V)
            final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandle, 2, type.parameterType(
                    1));
            final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
                    linkerServices, operations);

            final MethodHandle fallbackFolded;
            if(nextComponent == null) {
                // Object(MethodHandle)->Object(MethodHandle, O, N, V); returns constant null
                fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_METHOD_HANDLE, 1,
                        type.parameterList()).asType(type.insertParameterTypes(0, MethodHandle.class));
            } else {
                // Object(O, N, V)->Object(MethodHandle, O, N, V); adapts the next component's invocation to drop the
                // extra argument resulting from fold
                fallbackFolded = MethodHandles.dropArguments(nextComponent.getGuardedInvocation().getInvocation(),
                        0, MethodHandle.class);
            }

            // fold(R(MethodHandle, O, N, V), MethodHandle(O, N, V))
            final MethodHandle compositeSetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
                        IS_METHOD_HANDLE_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter);
            if(nextComponent == null) {
                return getClassGuardedInvocationComponent(compositeSetter, type);
            }
            return nextComponent.compose(compositeSetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
        }
        case 3: {
            // Must have two arguments: target object and property value
            assertParameterCount(callSiteDescriptor, 2);
            final GuardedInvocation gi = createGuardedDynamicMethodInvocation(callSiteDescriptor, linkerServices,
                    callSiteDescriptor.getNameToken(CallSiteDescriptor.NAME_OPERAND), propertySetters);
            // If we have a property setter with this name, this composite operation will always stop here
            if(gi != null) {
                return new GuardedInvocationComponent(gi, clazz, ValidationType.EXACT_CLASS);
            }
            // If we don't have a property setter with this name, always fall back to the next operation in the
            // composite (if any)
            return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, operations);
        }
        default: {
            // More than two name components; don't know what to do with it.
            return null;
        }
    }
}
 
开发者ID:SunburstApps,项目名称:OpenJSharp,代码行数:81,代码来源:AbstractJavaLinker.java

示例15: testInterfaceCast

import java.lang.invoke.MethodType; //导入方法依赖的package包/类
public void testInterfaceCast(MethodHandle mh, Class<?> ctype,
                                               boolean doret, boolean docast) throws Throwable {
    MethodHandle mh0 = mh;
    if (verbosity > 1)
        System.out.println("mh="+mh+", ctype="+ctype.getName()+", doret="+doret+", docast="+docast);
    String normalRetVal = "normal return value";
    MethodType mt = mh.type();
    MethodType mt0 = mt;
    if (doret)  mt = mt.changeReturnType(ctype);
    else        mt = mt.changeParameterType(0, ctype);
    if (docast) mh = MethodHandles.explicitCastArguments(mh, mt);
    else        mh = mh.asType(mt);
    assertEquals(mt, mh.type());
    MethodType mt1 = mt;
    // this bit is needed to make the interface types disappear for invokeWithArguments:
    mh = MethodHandles.explicitCastArguments(mh, mt.generic());
    Class<?>[] step = {
        mt1.parameterType(0),  // param as passed to mh at first
        mt0.parameterType(0),  // param after incoming cast
        mt0.returnType(),      // return value before cast
        mt1.returnType(),      // return value after outgoing cast
    };
    // where might a checkCast occur?
    boolean[] checkCast = new boolean[step.length];
    // the string value must pass each step without causing an exception
    if (!docast) {
        if (!doret) {
            if (step[0] != step[1])
                checkCast[1] = true;  // incoming value is cast
        } else {
            if (step[2] != step[3])
                checkCast[3] = true;  // outgoing value is cast
        }
    }
    boolean expectFail = false;
    for (int i = 0; i < step.length; i++) {
        Class<?> c = step[i];
        if (!checkCast[i])  c = i2o(c);
        if (!c.isInstance(normalRetVal)) {
            if (verbosity > 3)
                System.out.println("expect failure at step "+i+" in "+Arrays.toString(step)+Arrays.toString(checkCast));
            expectFail = true;
            break;
        }
    }
    countTest(!expectFail);
    if (verbosity > 2)
        System.out.println("expectFail="+expectFail+", mt="+mt);
    Object res;
    try {
        res = mh.invokeWithArguments(normalRetVal);
    } catch (Exception ex) {
        res = ex;
    }
    boolean sawFail = !(res instanceof String);
    if (sawFail != expectFail) {
        System.out.println("*** testInterfaceCast: mh0 = "+mh0);
        System.out.println("  retype using "+(docast ? "explicitCastArguments" : "asType")+" to "+mt+" => "+mh);
        System.out.println("  call returned "+res);
        System.out.println("  expected "+(expectFail ? "an exception" : normalRetVal));
    }
    if (!expectFail) {
        assertFalse(res.toString(), sawFail);
        assertEquals(normalRetVal, res);
    } else {
        assertTrue(res.toString(), sawFail);
    }
}
 
开发者ID:AdoptOpenJDK,项目名称:openjdk-jdk10,代码行数:69,代码来源:MethodHandlesTest.java


注:本文中的java.lang.invoke.MethodType.returnType方法示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。