In the following code I am returning a class that extends the type of Entity given the name of the class (it then corrects it so that Class.forName
can find it properly).
How can I modify this so that I can still return a class that extends Entity without using @SuppressWarnings("unchecked")
?
I tired a few variations using T
and just ?
but couldn't come up with an answer.
@SuppressWarnings("unchecked")
public static Class<? extends Entity> getProjectile(String name) {
if (name.equalsIgnoreCase("ARROW"))
name = "Arrow";
else if (name.equalsIgnoreCase("ENDERPEARL"))
name = "EnderPearl";
else if (name.equalsIgnoreCase("EXPERIENCEORB"))
name = "ExperienceOrb";
else if (name.equalsIgnoreCase("FIREBALL"))
name = "Fireball";
else if (name.equalsIgnoreCase("FIREWORK"))
name = "Firework";
else if (name.equalsIgnoreCase("SMALLFIREBALL"))
name = "SmallFireball";
else if (name.equalsIgnoreCase("SNOWBALL"))
name = "Snowball";
else
name = "Egg";
try {
return (Class<? extends Entity>) Class.forName("org.bukkit.entity." + name);
} catch (ClassNotFoundException e) {
return Egg.class;
}
}
You can't. Class.forName(String)
is declared as returning a reference of type Class<?>
which you then have to cast if you want it to conform to Class<? extends Entity>
Class<? extends Entity>
This cast is unsafe so the compiler warns you.
The alternative is to have the actual Class
objects in the if-else
block instead of the names.
If you can access the class at compile time you can just return, say org.bukkit.entity.Egg.class
instead of calling forName
. If you can't you're stuck with the annotation.
Compiler can't guess whether class extends Entity
just by looking at possible values for Class.forName(...)
call.
You can use a Class aClass
variable instead of String name
for storing answer to avoid warning:
public static Class<? extends Entity> getProjectile(String name) {
Class<? extends Entity> ans;
if (name.equalsIgnoreCase("ARROW"))
ans = Arrow.class;
else if (name.equalsIgnoreCase("ENDERPEARL"))
ans = EnderPearl.class;
else if (name.equalsIgnoreCase("EXPERIENCEORB"))
ans = ExperienceOrb.class;
else if (name.equalsIgnoreCase("FIREBALL"))
ans = Fireball.class;
else if (name.equalsIgnoreCase("FIREWORK"))
ans = Firework.class;
else if (name.equalsIgnoreCase("SMALLFIREBALL"))
ans = SmallFireball.class;
else if (name.equalsIgnoreCase("SNOWBALL"))
ans = Snowball.class;
else
ans = Egg.class;
return ans;
}
Answer to your question: Class.forname
isn't very 'safe' code, so you'll get compile messages. I'd say stick with what you have, as it works.
A few remarks: rather than that massive if block to determine the entity child's name, use the following code instead.
name = name.toLowerCase();
name = name.substring(0,1).toUpperCase() + name.substring(1);
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.