Skip to content

Commit 47dea2e

Browse files
authored
Improve error message when abstract class cannot be constructed (#1814)
1 parent 565b7a1 commit 47dea2e

File tree

2 files changed

+65
-0
lines changed

2 files changed

+65
-0
lines changed

gson/src/main/java/com/google/gson/internal/ConstructorConstructor.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.lang.reflect.Constructor;
2020
import java.lang.reflect.InvocationTargetException;
21+
import java.lang.reflect.Modifier;
2122
import java.lang.reflect.ParameterizedType;
2223
import java.lang.reflect.Type;
2324
import java.util.ArrayDeque;
@@ -99,6 +100,11 @@ public <T> ObjectConstructor<T> get(TypeToken<T> typeToken) {
99100
}
100101

101102
private <T> ObjectConstructor<T> newDefaultConstructor(Class<? super T> rawType) {
103+
// Cannot invoke constructor of abstract class
104+
if (Modifier.isAbstract(rawType.getModifiers())) {
105+
return null;
106+
}
107+
102108
final Constructor<? super T> constructor;
103109
try {
104110
constructor = rawType.getDeclaredConstructor();
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.google.gson.internal;
2+
3+
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.fail;
5+
6+
import java.lang.reflect.Type;
7+
import java.util.Collections;
8+
import java.util.Map;
9+
10+
import org.junit.Test;
11+
12+
import com.google.gson.InstanceCreator;
13+
import com.google.gson.reflect.TypeToken;
14+
15+
public class ConstructorConstructorTest {
16+
private static final Map<Type, InstanceCreator<?>> NO_INSTANCE_CREATORS = Collections.emptyMap();
17+
18+
private abstract static class AbstractClass {
19+
@SuppressWarnings("unused")
20+
public AbstractClass() { }
21+
}
22+
private interface Interface { }
23+
24+
/**
25+
* Verify that ConstructorConstructor does not try to invoke no-arg constructor
26+
* of abstract class.
27+
*/
28+
@Test
29+
public void testGet_AbstractClassNoArgConstructor() {
30+
ConstructorConstructor constructorFactory = new ConstructorConstructor(NO_INSTANCE_CREATORS, true);
31+
ObjectConstructor<AbstractClass> constructor = constructorFactory.get(TypeToken.get(AbstractClass.class));
32+
try {
33+
constructor.construct();
34+
fail("Expected exception");
35+
} catch (RuntimeException exception) {
36+
assertEquals(
37+
"Unable to create instance of class com.google.gson.internal.ConstructorConstructorTest$AbstractClass. "
38+
+ "Registering an InstanceCreator or a TypeAdapter for this type, or adding a no-args constructor may fix this problem.",
39+
exception.getMessage()
40+
);
41+
}
42+
}
43+
44+
@Test
45+
public void testGet_Interface() {
46+
ConstructorConstructor constructorFactory = new ConstructorConstructor(NO_INSTANCE_CREATORS, true);
47+
ObjectConstructor<Interface> constructor = constructorFactory.get(TypeToken.get(Interface.class));
48+
try {
49+
constructor.construct();
50+
fail("Expected exception");
51+
} catch (RuntimeException exception) {
52+
assertEquals(
53+
"Unable to create instance of interface com.google.gson.internal.ConstructorConstructorTest$Interface. "
54+
+ "Registering an InstanceCreator or a TypeAdapter for this type, or adding a no-args constructor may fix this problem.",
55+
exception.getMessage()
56+
);
57+
}
58+
}
59+
}

0 commit comments

Comments
 (0)