问题
I'm creating a game. When I'm extending my Block class it shows an error.
Error: Implicit super constructor Block() is undefined. Must explicitly invoke another constructor
Code:
Game.java:
package lt.projecturanium;
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;
import java.util.HashMap;
import javax.swing.JFrame;
import lt.projecturanium.blocks.Block;
import lt.projecturanium.blocks.BlockRectangle;
import lt.projecturanium.entity.Player;
@SuppressWarnings("unused")
public class Game extends Canvas implements Runnable{
private static final long serialVersionUID = 1L;
private static JFrame _frame;
public static Game _instance;
private static final String TITLE = "Project Uranium";
private static final int WIDTH = 650;
private static final int HEIGHT = WIDTH * 3 / 4;
private static final int UPDATE_RATE = 50;
private static final int RENDER_RATE = 100;
public static HashMap<Block, Coordinates> blocks = new HashMap<Block, Coordinates>();
public int rectx = 0;
public int recty = 0;
public int rectID = 0;
public boolean hitted = false;
public float interpolation;
public static final Dimension SIZE = new Dimension(WIDTH, HEIGHT);
private Thread _thread;
private boolean _running;
private int _totalTicks = 0;
private int _tps = 0;
private int _fps = 0;
public Game()
{
_instance = this;
setPreferredSize(SIZE);
setMinimumSize(SIZE);
setMaximumSize(SIZE);
_frame = new JFrame(TITLE);
_frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
_frame.setLayout(new BorderLayout());
_frame.add(_instance, BorderLayout.CENTER);
_frame.pack();
_frame.setResizable(false);
_frame.setLocationRelativeTo(null);
_frame.setVisible(true);
createBufferStrategy(2);
blocks.put(new Block(new BlockRectangle(200)), new Coordinates(30, 50));
}
public synchronized void start()
{
_running = true;
_thread = new Thread(this, TITLE+"_main");
_thread.start();
}
public synchronized void stop()
{
_running = false;
if (_thread != null)
{
try {
_thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void paint(Graphics g) {
super.paint(g); // fixes the immediate problem.
Graphics2D g2 = (Graphics2D) g;
g2.drawString("FPS: " + _fps + "\n TPS: " + _tps, 10, 10);
if (hitted)
{
recty = 0;
rectx += 21;
rectID++;
blocks.put(new Block(new BlockRectangle(rectID)), new Coordinates(rectx, recty));
hitted = false;
}
recty++;
g2.drawImage(Player.getTexture(), 60, 60, null);
g2.drawRect(rectx, recty, 20, 20);
g2.setColor(new Color(101, 67, 33));
g2.fillRect(0, 430, getWidth(), getHeight());
g2.setColor(new Color(0, 100, 0));
g2.fillRect(0, 420, getWidth(), 10);
g2.setColor(Color.BLACK);
if (recty == (419 - 20))
{
hitted = true;
}
}
public void run() {
double lastUpdateTime = System.nanoTime();
double lastRenderTime = lastUpdateTime;
final int ns = 1000000000;
final double nsPerUpdate = (double) ns / UPDATE_RATE;
final double nsPerRender = (double) ns / RENDER_RATE;
final int maxUpdatesBeforeRender = 5;
int lastSecond = (int) (lastUpdateTime / ns);
int tickCount = 0;
int renderCount = 0;
while (_running) {
long currTime = System.nanoTime();
int tps = 0;
while ((currTime - lastUpdateTime) > nsPerUpdate && tps < maxUpdatesBeforeRender) {
update();
tickCount++;
_totalTicks++;
tps++;
lastUpdateTime += nsPerUpdate;
interpolation = Math.min(1.0F, (float) ((currTime - lastUpdateTime) / nsPerUpdate));
render(interpolation, getGraphics());
}
if (currTime - lastUpdateTime > nsPerUpdate) {
lastUpdateTime = currTime - nsPerUpdate;
}
if (currTime - lastRenderTime == maxUpdatesBeforeRender + 1)
{
render(interpolation, getGraphics());
}
renderCount++;
lastRenderTime = currTime;
int currSecond = (int) (lastUpdateTime / ns);
if (currSecond > lastSecond) {
_tps = tickCount;
_fps = renderCount;
tickCount = 0;
renderCount = 0;
lastSecond = currSecond;
_frame.setTitle(TITLE + " | TPS: " + _tps + " | FPS: "+ _fps);
}
while (currTime - lastRenderTime < nsPerRender && currTime - lastUpdateTime < nsPerUpdate) {
Thread.yield();
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
currTime = System.nanoTime();
}
}
}
public void update()
{
_frame.pack();
}
public void render(float interp, Graphics g)
{
BufferStrategy myStrategy = getBufferStrategy();
Graphics gra = myStrategy.getDrawGraphics();
paint(gra);
g.dispose();
myStrategy.show();
//System.out.println("Grass x: " + blocks.get("grass").getX() + " y: " + blocks.get("grass").getY());
System.out.println("Stone x: " + blocks.get(new Block(new BlockRectangle(rectID))).getX() + " y: " + blocks.get(new Block(new BlockRectangle(rectID))).getY());
}
}
Block.java:
package lt.projecturanium.blocks;
public class Block {
private Block block;
public Block (Block block){
this.block = this;
}
public Block getBlock() {
return block;
}
public Block getBlockById(int id)
{
return block;
}
}
BlockRectangle.java:
package lt.projecturanium.blocks;
import java.awt.Image;
import java.io.IOException;
import java.util.HashMap;
import javax.imageio.ImageIO;
import lt.projecturanium.Game;
public class BlockRectangle extends Block{
private int id;
private static HashMap<Integer, BlockRectangle> rects = new HashMap<Integer, BlockRectangle>();
public BlockRectangle(int id)
{
this.id = id;
}
public int getID()
{
return this.id;
}
public static BlockRectangle getByID(int id)
{
return rects.get(id);
}
public static Image getTexture()
{
try{
return ImageIO.read(Game._instance.getClass().getClassLoader().getResource("../res/player.png"));
}
catch(IOException e)
{
e.printStackTrace();
}
return null;
}
}
Coordinates.java:
package lt.projecturanium;
public class Coordinates {
private int x;
private int y;
public Coordinates(int x, int y)
{
this.x = x;
this.y = y;
}
public int getX()
{
return this.x;
}
public int getY()
{
return this.y;
}
}
回答1:
public class BlockRectangle extends Block
BlockRectangle extends Block. So in the constructor of BlockRectangle, you must at first call a constructor of Block via super().
public BlockRectangle(int id){
//This line is optional if Block has an empty constructor.
super([...]);
this.id = id;
}
If Block had an empty constructor, it would have been implicitly called. That's not the case. Hence, you must exmplicitly call super() yourself (or define an empty constructor).
Note : If Block had no constructor at all, an empty constructor would have been implicitly created.
回答2:
BlockRectangle(...) needs to call super(null) because the implicit (=not written in code)
super() (Block()) does not exist.
回答3:
Default constructor only exists if you haven't defined any other constructor for the class. Constructors of subclassess silently call super() if no other constructor is called manually, which means they attempt to call a default constructor.
You can solve this problem by creating a parameterless constructor in Block class yourself or by calling the existing constructor through super in each of the subclasses.
回答4:
Since you defined a constructor, Java no longer provides a default constructor. Therefore you must define a nullary constructor yourself:
public Block()
{
}
Also, I'm not sure why you are keeping a reference of a Block to itself. Given the methods you have on the Block class, it looks like you may want to learn more about inheritance. I think you are misusing it.
回答5:
You are getting this error because the constructor
public BlockRectangle(int id)
{
this.id = id;
}
implicitly calls the super no-argument constructor which should be Block(){}
As you have defined a constructor for your class explicitly, compiler will not provide a default no-argument constructor. So you should create it manually.
Add a no argument constructor Block(){} to your Block class and it will solve your problem.
回答6:
A Java class has an implicit default constructor as long as you don't define another one explicitly. This is what you did in your Block class.
Now if you have a subclass with a constructor, the default constructor of the superclass is implictly called.
public BlockRectangle(int id)
{
// Tries to call super() implictly which doesn't exist anymore
this.id = id;
}
You can fix this by explicitly defining an additional, default constructor in the superclass
public Block()
{
}
or by explicitly calling the non default superclass constructor
public BlockRectangle(int id)
{
super(new Block());
this.id = id;
}
As for another topic: Your constructor in Block really doesn't make any sense:
public Block (Block block){
this.block = this;
}
You are ignoring the parameter and setting your field to this. It makes no sense as the this referenence is always available anyways inside the class.
来源:https://stackoverflow.com/questions/18827888/implicit-super-constructor-block-is-undefined