0

I was trying to make kotlin library, but when I test it (I do it in java, sorry for that - I am new to kotlin), it throws error. Where's problem?

Original code, which I am making the kotlin library from:

package me.engo.originalproject;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.swing.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Objects;
import java.util.Random;

public class Main
{
    private boolean button = true;
    private Clip clip = null;
    private int i = 0;
    private JPanel panel;
    private JLabel label;
    private static JFrame frame;

    public Main()
    {
        label.addMouseListener(new MouseAdapter()
        {
            @Override
            public void mouseClicked(MouseEvent e)
            {
                if (e.getButton() == 1 && button)
                {
                    new Thread(() -> {
                        label.setIcon(new ImageIcon(Objects.requireNonNull(Thread.currentThread().getContextClassLoader().getResource("dead.png"))));
                        frame.setTitle(String.valueOf(Integer.parseInt(frame.getTitle()) + 1));
                        button = false;

                        new Thread(() -> {
                            try
                            {
                                if (clip != null) clip.stop();

                                int random = new Random().nextInt(4) + 1;

                                if (i != 0)
                                {
                                    while (i == random)
                                    {
                                        random = new Random().nextInt(4) + 1;
                                    }
                                }

                                i = random;

                                AudioInputStream audioIn = AudioSystem.getAudioInputStream(Thread.currentThread().getContextClassLoader().getResource("0" + random + ".wav"));
                                clip = AudioSystem.getClip();
                                clip.open(audioIn);
                                clip.start();
                            } catch (Exception exc)
                            {
                                exc.printStackTrace();
                            }
                        }).start();

                        try
                        {
                            Thread.sleep(100);
                        } catch (Exception ex)
                        {
                            ex.printStackTrace();
                        }

                        label.setIcon(new ImageIcon(Objects.requireNonNull(Thread.currentThread().getContextClassLoader().getResource("alive.png"))));
                        button = true;
                    }).start();
                }
            }
        });
    }

    public static void main(String[] args)
    {
        frame = new JFrame("0");
        frame.setContentPane(new Main().panel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
        frame.setResizable(false);
    }
}

The kotlin library class:

package me.engo.library

import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent
import java.util.*
import javax.sound.sampled.AudioSystem
import javax.sound.sampled.Clip
import javax.swing.ImageIcon
import javax.swing.JFrame
import javax.swing.JLabel
import javax.swing.JPanel


class Template(val sounds: Int, private val panel: JPanel, val label: JLabel)
{
    var button: Boolean = true
    lateinit var frame: JFrame
    lateinit var clip: Clip
    var i: Int = 0

    fun doListener()
    {
        println("A")
        label.addMouseListener(object : MouseAdapter() {
            override fun mouseClicked(e: MouseEvent) {
                println("B")
                if (e.button == 1 && button) {
                    println("C")
                    Thread {
                        label.icon = ImageIcon(
                            Objects.requireNonNull(
                                Thread.currentThread().contextClassLoader.getResource("dead.png")
                            )
                        )
                        frame.title = (frame.title.toInt() + 1).toString()
                        button = false

                        if (sounds != 0)
                        {
                            Thread {
                                try {
                                    if (clip != null) clip.stop()

                                    var random: Int = Random().nextInt(sounds - 1) + 1

                                    if (i != 0) {
                                        while (i == random) {
                                            random = Random().nextInt(sounds - 1) + 1
                                        }
                                    }

                                    i = random
                                    val audioIn = AudioSystem.getAudioInputStream(
                                        Thread.currentThread().contextClassLoader.getResource("0$random.wav")
                                    )

                                    clip = AudioSystem.getClip()
                                    clip.open(audioIn)
                                    clip.start()
                                } catch (exc: Exception) {
                                    exc.printStackTrace()
                                }
                            }.start()
                        }

                        try {
                            Thread.sleep(100)
                        } catch (ex: Exception) {
                            ex.printStackTrace()
                        }
                        label.icon = ImageIcon(
                            Objects.requireNonNull(
                                Thread.currentThread().contextClassLoader.getResource("alive.png")
                            )
                        )
                        button = true
                    }.start()
                }
            }
        })
    }

    fun doMain()
    {
        label.icon = ImageIcon(
            Objects.requireNonNull(
                Thread.currentThread().contextClassLoader.getResource("alive.png")
            )
        )

        frame = JFrame("0")
        frame.contentPane = panel
        frame.defaultCloseOperation = JFrame.EXIT_ON_CLOSE
        frame.pack()
        frame.isVisible = true
        frame.isResizable = false
    }
}

The java test void:

package me.engo.library;

import javax.swing.*;

public class Test
{
    private JPanel panel;
    private JLabel label;

    static Template template = new Template(5, new Test().panel, new Test().label);

    public static void main(String[] args)
    {
        template.doMain();
    }

    public Test()
    {
        template.doListener();
    }
}

IDK, whats wrong here...

Btw the exception:

Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.NullPointerException
    at me.engo.killtemplate.Test.<init>(Test.java:19)
    at me.engo.killtemplate.Test.<clinit>(Test.java:10)

I am sorry, if is it obvious, but I dont see anything. Thank you for helping.

ENGO_150
  • 3
  • 2

1 Answers1

0

You can see the problem just from your Test class.  Consider what's happening when the JVM loads the class:

  • After getting the code &c, it runs any static initialisers.  This class has one: the static Template template field.  So it evaluates the initialiser expression:

    • To evaluate the initialiser expression, it constructs an instance of Template.  This calls the Template constructor:

      • The constructor calls a method on template.  However, template is not set yet!

template can't be set until the the JVM knows what to set it to, and it can't do that until the instance is constructed.

So (because all fields in Java start off set to null/0/false) template actually holds null at that point.  Hence the NullPointerException when trying to call a method on it.

Effectively, you have a deadlock: you can't set the template field until you've created an instance; but you can't create an instance until you've set the template field.

To fix this, you need to break that deadlock somehow.  (Perhaps the simplest way would be to check whether the template is null before trying to use it in the constructor.)

gidds
  • 9,862
  • 1
  • 12
  • 16