46 private final ClassDesc owner;
47 private final String name;
48 private final MethodTypeDesc invocationType;
49
50 /**
51 * Constructs a {@linkplain DirectMethodHandleDescImpl} for a method or field
52 * from a kind, owner, name, and type
53 *
54 * @param kind the kind of the method handle
55 * @param owner the declaring class or interface for the method
56 * @param name the unqualified name of the method (ignored if {@code kind} is {@code CONSTRUCTOR})
57 * @param type the lookup type of the method
58 * @throws NullPointerException if any non-ignored argument is null
59 * @throws IllegalArgumentException if {@code kind} describes a field accessor,
60 * and {@code type} is not consistent with that kind of field accessor, or if
61 * {@code kind} describes a constructor, and the return type of {@code type}
62 * is not {@code void}
63 * @jvms 4.2.2 Unqualified Names
64 */
65 DirectMethodHandleDescImpl(Kind kind, ClassDesc owner, String name, MethodTypeDesc type) {
66 if (kind == CONSTRUCTOR)
67 name = "<init>";
68
69 requireNonNull(kind);
70 validateClassOrInterface(requireNonNull(owner));
71 validateMemberName(requireNonNull(name), true);
72 requireNonNull(type);
73
74 switch (kind) {
75 case CONSTRUCTOR -> validateConstructor(type);
76 case GETTER -> validateFieldType(type, false, true);
77 case SETTER -> validateFieldType(type, true, true);
78 case STATIC_GETTER -> validateFieldType(type, false, false);
79 case STATIC_SETTER -> validateFieldType(type, true, false);
80 }
81
82 this.kind = kind;
83 this.owner = owner;
84 this.name = name;
85 if (kind.isVirtualMethod())
86 this.invocationType = type.insertParameterTypes(0, owner);
87 else if (kind == CONSTRUCTOR)
88 this.invocationType = type.changeReturnType(owner);
89 else
90 this.invocationType = type;
91 }
92
93 private static void validateFieldType(MethodTypeDesc type, boolean isSetter, boolean isVirtual) {
94 boolean isVoid = type.returnType().descriptorString().equals("V");
95 int expectedParams = (isSetter ? 1 : 0) + (isVirtual ? 1 : 0);
96 if (isVoid != isSetter
97 || type.parameterCount() != expectedParams
98 || (isVirtual && type.parameterType(0).isPrimitive())) {
99 String expectedType = String.format("(%s%s)%s", (isVirtual ? "R" : ""),
100 (isSetter ? "T" : ""), (isSetter ? "V" : "T"));
101 throw new IllegalArgumentException(String.format("Expected type of %s for getter, found %s", expectedType, type));
102 }
103 }
104
105 private static void validateConstructor(MethodTypeDesc type) {
106 if (!type.returnType().descriptorString().equals("V")) {
107 throw new IllegalArgumentException(String.format("Expected type of (T*)V for constructor, found %s", type));
108 }
109 }
110
111 @Override
112 public Kind kind() { return kind; }
113
114 @Override
115 public int refKind() { return kind.refKind; }
116
117 @Override
118 public boolean isOwnerInterface() { return kind.isInterface; }
119
120 @Override
121 public ClassDesc owner() {
122 return owner;
123 }
124
125 @Override
|
46 private final ClassDesc owner;
47 private final String name;
48 private final MethodTypeDesc invocationType;
49
50 /**
51 * Constructs a {@linkplain DirectMethodHandleDescImpl} for a method or field
52 * from a kind, owner, name, and type
53 *
54 * @param kind the kind of the method handle
55 * @param owner the declaring class or interface for the method
56 * @param name the unqualified name of the method (ignored if {@code kind} is {@code CONSTRUCTOR})
57 * @param type the lookup type of the method
58 * @throws NullPointerException if any non-ignored argument is null
59 * @throws IllegalArgumentException if {@code kind} describes a field accessor,
60 * and {@code type} is not consistent with that kind of field accessor, or if
61 * {@code kind} describes a constructor, and the return type of {@code type}
62 * is not {@code void}
63 * @jvms 4.2.2 Unqualified Names
64 */
65 DirectMethodHandleDescImpl(Kind kind, ClassDesc owner, String name, MethodTypeDesc type) {
66 if (kind == CONSTRUCTOR) {
67 name = "<init>";
68 }
69
70 requireNonNull(kind);
71 validateClassOrInterface(requireNonNull(owner));
72 validateMemberName(requireNonNull(name), true);
73 requireNonNull(type);
74
75 switch (kind) {
76 case CONSTRUCTOR -> validateObjectConstructor(type);
77 case GETTER -> validateFieldType(type, false, true);
78 case SETTER -> validateFieldType(type, true, true);
79 case STATIC_GETTER -> validateFieldType(type, false, false);
80 case STATIC_SETTER -> validateFieldType(type, true, false);
81 }
82
83 this.kind = kind;
84 this.owner = owner;
85 this.name = name;
86 if (kind.isVirtualMethod())
87 this.invocationType = type.insertParameterTypes(0, owner);
88 else if (kind == CONSTRUCTOR)
89 this.invocationType = type.changeReturnType(owner);
90 else
91 this.invocationType = type;
92 }
93
94 private static void validateFieldType(MethodTypeDesc type, boolean isSetter, boolean isVirtual) {
95 boolean isVoid = type.returnType().descriptorString().equals("V");
96 int expectedParams = (isSetter ? 1 : 0) + (isVirtual ? 1 : 0);
97 if (isVoid != isSetter
98 || type.parameterCount() != expectedParams
99 || (isVirtual && type.parameterType(0).isPrimitive())) {
100 String expectedType = String.format("(%s%s)%s", (isVirtual ? "R" : ""),
101 (isSetter ? "T" : ""), (isSetter ? "V" : "T"));
102 throw new IllegalArgumentException(String.format("Expected type of %s for getter, found %s", expectedType, type));
103 }
104 }
105
106 private static void validateObjectConstructor(MethodTypeDesc type) {
107 if (!type.returnType().descriptorString().equals("V")) {
108 throw new IllegalArgumentException(String.format("Expected type of (T*)V for constructor, found %s", type));
109 }
110 }
111
112 @Override
113 public Kind kind() { return kind; }
114
115 @Override
116 public int refKind() { return kind.refKind; }
117
118 @Override
119 public boolean isOwnerInterface() { return kind.isInterface; }
120
121 @Override
122 public ClassDesc owner() {
123 return owner;
124 }
125
126 @Override
|