# TimerTask Übergabe an andere Klasse



## Chefselber (12. Jul 2021)

Hallo Gemeinde,

ich bekomme hier eine NullPointerException.
Vielleicht hat jemand Rat?!

Hier wird Aufgabe() aufgerufen


```
public Gasübernahme() {
        initComponents();
         try
          {   
              BufferedImage image = ImageIO.read(new File("E:VISU/Gasübernahme.png"));     
            }
    catch (IOException e)
    {
      // log the exception
      // re-throw if desired
    }
      init();
        
         java.util.Timer timer = new java.util.Timer();
    
      timer.scheduleAtFixedRate(new Aufgabe(),10000,2000);
        
        
        
    }
```


// Klasse Aufgabe


```
public class Aufgabe extends TimerTask implements Runnable{
  
    private Gasübernahme gasübernahme;
   //  private Gaszufuhr gaszufuhr;
    
 
    
    
     @Override
    public void run() {
        
        Einlesen();
    }
 
    public Aufgabe()
    {
        
    
    
    }
    
  
    
    
    // hier die Daten lesen
    public void Einlesen()
    {
      
       gasübernahme.Einlesen();
      
  
    }
    
 
}
```

Selbst wenn ich mit new Aufgabe(this) den TimerTask starte, kommt eine Exception.

Was mache ich hier falsch?


MfG Chef


----------



## kneitzel (12. Jul 2021)

Die Instanzvariable gasübernahme wird nie gesetzt und ist daher null. Du musst der Variablen erst was zuweisen, damit du darauf Methoden aufrufen kannst.


----------



## Chefselber (13. Jul 2021)

Hallo,
vielen Dank für deine Antwort.

Also


```
timer.scheduleAtFixedRate(new Aufgabe(this),10000,2000);
```

und 


```
public class Aufgabe extends TimerTask implements Runnable{
 
    private Gasübernahme gasübernahme;
   //  private Gaszufuhr gaszufuhr;
    
 
    
    
     @Override
    public void run() {
        
        Einlesen();
    }
 
    public Aufgabe(Gasübernahme gasübernahme)
    {
        this.gasübernahme = gasübernahme;
    
    
    }
    
 
    
    
    // hier die Daten lesen
    public void Einlesen()
    {
      
       gasübernahme.Einlesen();
      
 
    }
    
 
}
```


funktioniert aber auch nicht.
Ich versteh nicht warum!


----------



## Jw456 (13. Jul 2021)

Was ich bei deinem Code etwas unsinnig finde ist das runnable. Du erbst von timertask. Übergibst dieses Task an den Timer. Wozu das runnable?





__





						Java ist auch eine Insel
					

Java ist auch eine Insel - Programmieren für die Java 2-Plattform in der Version 5 (Tiger-Release) - ISBN 3-89842-526-6



					dev.usw.at
				




Ein Objekt von deinem Gasübernahme erstellst du keines hast this den Context übergeben. 
Das wäre dann ein Objekt des Aufrufer selbst.

Denn Context der aufrufen Klasse also den vom ui Thread übergibst du sicherlich weil du in dem timertask Thread Eine Ausgabe auf den UI machen willst. Nur ob das so geht aus einen Thread auf den UI zu kommen?


----------



## Chefselber (13. Jul 2021)

Ja Objekt aus dem TimerTask an die Aufgabe Klasse,

diese soll dann eine Methode in Gasübernahme beschreiben.



Entferne ich die Run Methode in Aufgabe kommt folgender Fehler:

Aufgabe is not abstract and does not override abstract run() in TimerTask.


----------



## Jw456 (13. Jul 2021)

Dann auch das interface in der Klasse entfernen.


----------



## Chefselber (13. Jul 2021)

Ok. Habe das Interface - implements entfernt.
Selber Fehler.
liegt wohl an 
public class Aufgabe extends TimerTask 
?


----------



## Jw456 (13. Jul 2021)

Das wird nicht passen. Mit deinem this beim Aufruf übergibst du nicht die ref auf deine Klasse. In Android würde man den Context übergeben ob es diese Klasse auch unter Desktop java gibt weiß ich nicht. 

public Aufgabe(Context context ) würde ich in Android machen. Ich denke es gibt etwas ähnliches im normalen java auch.


----------



## Chefselber (13. Jul 2021)

Wie übergibt man dann eine Instanz? 

Also
Timer Klasse 2 (Aufgabe) wird von Klasse 1(BTB) aufgerufen. 
Klasse 3 (Gasübernahme) bekommt Aufruf von Timer Klasse 2 (Aufgabe)

Das muss doch mit "this" funktionieren


----------



## Jw456 (13. Jul 2021)

Context gibt es auch in Java.


----------



## kneitzel (13. Jul 2021)

Bitte lass Dich nicht verwirren. Du hast die Instanz von Gasübernahme richtig an den Konstruktor übergeben. Und diese weist Du auch korrekt der Instanzvariablen zu.

Der Punkt ist somit durchaus korrekt abgehakt. Daher wäre jetzt wichtig, was genau nicht funktioniert. Was für einen Fehler / Exception bekommst Du? Oder was ist das erwartete Verhalten und was für ein Verhalten hast Du?



Jw456 hat gesagt.:


> Context gibt es auch in Java.


Und wozu sollte er javax.naming.Context bei seinem Problem wie nutzen?


----------



## Chefselber (13. Jul 2021)

Exception in thread "Timer-1" java.lang.NullPointerException: Cannot invoke "Moka7Demo.Gasübernahme.Einlesen()" because "this.gasübernahme" is null
    at Moka7Demo.Aufgabe.run(Aufgabe.java:56)
    at java.base/java.util.TimerThread.mainLoop(Timer.java:556)
    at java.base/java.util.TimerThread.run(Timer.java:506)


bei diesem Code in Aufgabe:


```
*/
public class Aufgabe extends TimerTask implements Runnable
{
    private Gasübernahme gasübernahme;
     private Gaszufuhr gaszufuhr;
    
 
    
    
    
 
    public Aufgabe(Gasübernahme gasübernahme)
    {
        this.gasübernahme = gasübernahme;
    
    
    }
    
      public Aufgabe(Gaszufuhr gaszufuhr)
    {
        this.gaszufuhr = gaszufuhr;
    
    
    }
    
    
    // hier die Daten lesen
    public void Einlesen()
    {
      
    
      
  
    }

    @Override
    public void run() {
         gasübernahme.Einlesen();
    }

 
    
 
}
```


----------



## kneitzel (13. Jul 2021)

Zeig bitte die ganzen Klassen. So kann man nur raten.

Ein Rateversuch:
Ist das `timer.scheduleAtFixedRate(new Aufgabe(this),10000,2000);` wirklich in Gasübernahme? Oder hast Du das in Gaszufuhr (Weil Du da halt auch einen solchen Konstruktor hast?)

Weil es in der bisherigen Diskussion erwähnt wurde und von Dir wieder rückgängig gemacht wurde: Das "implements Runnable" kannst Du rausnehmen. Das ist aber nicht falsch. TimerTask hat das bereits und da Du von TimerTask ableitest hast Du das Interface schon drin. Aber es noch einmal anzugeben verändert nichts. Das extends TimerTasks musst Du aber natürlich haben, weil Timer.schedule ein TimerTask als Parameter haben will.


----------



## Chefselber (14. Jul 2021)

Guten Morgen,

hier mal aktueller Stand:

[CODE lang="java" title="Gasübernahme"]/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package Moka7Demo;
import java.awt.*;
import javax.swing.*;
import javax.imageio.*;
import java.io.*;
import java.net.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
/**
 *
 *
 */
public class Gasübernahme extends javax.swing.JFrame {


    public static Komponenten V_931AK01 = new Komponenten();
    public static Komponenten V_931AK02 = new Komponenten();
       public static Komponenten P_931I41= new Komponenten();
    /**
     * Creates new form Gasübernahme
     *
     */
    public Gasübernahme() {
        initComponents();
         try
          {   
              BufferedImage image = ImageIO.read(new File("E:/VISU/Gasübernahme.png"));     
            }
    catch (IOException e)
    {
      // log the exception
      // re-throw if desired
    }
      init();

         java.util.Timer timer = new java.util.Timer();

      timer.scheduleAtFixedRate(new Aufgabe(this),10000,2000);



    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                         
    private void initComponents() {

        jLabel6 = new javax.swing.JLabel();
        jLabel5 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        jLabel1 = new javax.swing.JLabel();
        jButton3 = new javax.swing.JButton();
        jButton4 = new javax.swing.JButton();
        jLabel2 = new javax.swing.JLabel();
        jButton5 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        getContentPane().setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());

        jLabel6.setText("931I42");
        getContentPane().add(jLabel6, new org.netbeans.lib.awtextra.AbsoluteConstraints(940, 720, -1, -1));

        jLabel5.setText("jLabel5");
        getContentPane().add(jLabel5, new org.netbeans.lib.awtextra.AbsoluteConstraints(210, 710, -1, -1));

        jLabel4.setText("jLabel4");
        getContentPane().add(jLabel4, new org.netbeans.lib.awtextra.AbsoluteConstraints(570, 610, -1, -1));

        jLabel3.setText("jLabel3");
        getContentPane().add(jLabel3, new org.netbeans.lib.awtextra.AbsoluteConstraints(550, 740, -1, -1));

        jLabel1.setText("jLabel1");
        getContentPane().add(jLabel1, new org.netbeans.lib.awtextra.AbsoluteConstraints(610, 710, 100, -1));

        jButton3.setText("931AK02");
        jButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton3ActionPerformed(evt);
            }
        });
        getContentPane().add(jButton3, new org.netbeans.lib.awtextra.AbsoluteConstraints(790, 560, -1, -1));

        jButton4.setText("931AK01");
        jButton4.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton4ActionPerformed(evt);
            }
        });
        getContentPane().add(jButton4, new org.netbeans.lib.awtextra.AbsoluteConstraints(260, 740, -1, -1));

        jLabel2.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Moka7Demo/Gasübernahme.png"))); // NOI18N
        jLabel2.setText("jLabel2");
        getContentPane().add(jLabel2, new org.netbeans.lib.awtextra.AbsoluteConstraints(30, 20, 1320, 770));

        jButton5.setText("jButton3");
        getContentPane().add(jButton5, new org.netbeans.lib.awtextra.AbsoluteConstraints(500, 500, -1, -1));

        pack();
    }// </editor-fold>                       

    private void init()
    {
        // Ventile
        V_931AK01.Kennung = "DB";
        V_931AK01.db_nr= 111;
        V_931AK01.adresse = 54;
        V_931AK01.bit = 0;

        V_931AK02.Kennung = "DB";
        V_931AK02.db_nr= 111;
        V_931AK02.adresse = 58;
        V_931AK02.bit = 0;

        // Drucksensor
      //   P_931I41
         P_931I41.Kennung = "DB";
         P_931I41.db_nr= 102;
        P_931I41.adresse = 26;

    }

    public void Einlesen(){
      //  jLabel6.setText( String.valueOf(Read.Read_float( 102, 26)));
       jLabel6.setText("dfgdfgga");




    }
    // 931AK01
    private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {                                         

        if (V_931AK01.Anwahl){
           V_931AK01.Anwahl = false;
            Read.Write_Bit(V_931AK01.Anwahl, V_931AK01.db_nr, V_931AK01.adresse, V_931AK01.bit);
           aktualisieren();
       return;
        }
         if (!V_931AK01.Anwahl)
           V_931AK01.Anwahl = true;
          Read.Write_Bit(V_931AK01.Anwahl, V_931AK01.db_nr, V_931AK01.adresse, V_931AK01.bit);
        aktualisieren();
    }                                       

    private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {                                         
         if (V_931AK02.Anwahl){
           V_931AK02.Anwahl = false;
           Read.Write_Bit(V_931AK02.Anwahl, V_931AK02.db_nr, V_931AK02.adresse, V_931AK02.bit);
            aktualisieren();
        return;
         }
         if (!V_931AK02.Anwahl)
           V_931AK02.Anwahl = true;
           Read.Write_Bit(V_931AK02.Anwahl, V_931AK02.db_nr, V_931AK02.adresse, V_931AK02.bit);
          aktualisieren();
    }                                       


    private void aktualisieren()
    {
        if (V_931AK02.Anwahl)
        {
            jButton3.setBackground(Color.green);
        }
            else
        {
            jButton3.setBackground(Color.LIGHT_GRAY);
        } 
          if (V_931AK01.Anwahl)
          {
              jButton4.setBackground(Color.green);
          }
              else
          {
              jButton4.setBackground(Color.LIGHT_GRAY);
          }
    }



    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(Gasübernahme.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(Gasübernahme.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(Gasübernahme.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(Gasübernahme.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
              //  new Gasübernahme().setVisible(true);

            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JButton jButton3;
    private javax.swing.JButton jButton4;
    private javax.swing.JButton jButton5;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    // End of variables declaration                   
}
[/CODE]


[CODE lang="java" title="Aufgabe Klasse"]/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package Moka7Demo;

import Moka7.S7;
import java.awt.Color;
import java.io.IOException;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.text.*;
import javax.swing.DefaultListModel;
/**
 *
 * @author
 */
public class Aufgabe extends TimerTask implements Runnable
{
    private Gasübernahme gasübernahme;
     private Gaszufuhr gaszufuhr;






    public Aufgabe(Gasübernahme gasübernahme)
    {
        this.gasübernahme = gasübernahme;


    }

      public Aufgabe(Gaszufuhr gaszufuhr)
    {
        // this.gaszufuhr = gaszufuhr;


    }


    // hier die Daten lesen
    public void Einlesen()
    {




    }

    @Override
    public void run() {
         gasübernahme.Einlesen();
    }




}[/CODE]


----------



## kneitzel (14. Jul 2021)

Ok, die main in Gasübernahme ist ja soweit alles auskommentiert - das verstärkt mich bei meiner Vermutung, dass Du eben nicht den Timer über Gasübernahme machst (mit dem Code, den Du hier zeigst) sondern dass Du über die Klasse Gaszufuhr gehst.

Prüf bitte genau, was Du startest und wo Du einen Timer erstellst. Die Stelle dürftest Du auch direkt finden als Fehler wenn Du den Konstruktor `public Aufgabe(Gaszufuhr gaszufuhr)` rauslöschst. Denn da, wo Du den Konstruktor nutzt, erzeugst Du eine Instanz von Aufgabe bei der gasübernahme null ist.


----------



## Jw456 (14. Jul 2021)

Eine zwischen Frage er startet den timer im construcktor von Gasübernahme. Wenn zu dem Zeitpunkt die Instanz schon verfügbar ist wäre das richtig.
Wann genau ist eine Instanz von einem Objekt fertig erstellt?

Was passiert wenn du garnichts in den timertask machst. Hast du da ich den Fehler.

Oder benutze Gasübernahme.this nicht nur this im sicher zugehen das du das richtige übergibst.


----------



## Jw456 (14. Jul 2021)

PS ich sehe gerade das du zwei fast gleiche construcktor in deinem timertask hast finde ich nicht gut. Bein Aufruf mit this ist nicht eindeutig welcher benutzt wird.


----------



## kneitzel (14. Jul 2021)

Jw456 hat gesagt.:


> Eine zwischen Frage er startet den timer im construcktor von Gasübernahme. Wenn zu dem Zeitpunkt die Instanz schon verfügbar ist wäre das richtig.
> Wann genau ist eine Instanz von einem Objekt fertig erstellt?


Die Instanz ist da schon verfügbar, aber die Initialisierung ist halt noch nicht durch. Dadurch kann es zu Problemen kommen a.la. eine Instanzvariable ist noch nicht initialisiert aber es wird bereits drauf zugegriffen und Du bekommst eine NPE.
Wenn dich der Ablauf bei der "Class Creation" interessiert: https://docs.oracle.com/javase/specs/jls/se16/html/jls-12.html#jls-12.5
Da findet sich auch die Reihenfolge, in der was passiert.



Jw456 hat gesagt.:


> Oder benutze Gasübernahme.this nicht nur this im sicher zugehen das du das richtige übergibst.


Etwas in der Art ist nicht notwendig. So der Timer über den Konstruktor so erzeugt wird, würde es funktionieren. Das kann man so auch jederzeit austesten.


----------



## kneitzel (14. Jul 2021)

Jw456 hat gesagt.:


> PS ich sehe gerade das du zwei fast gleiche construcktor in deinem timertask hast finde ich nicht gut. Bein Aufruf mit this ist nicht eindeutig welcher benutzt wird.


Warum ist das nicht eindeutig? Das ist eine normale Überladung. Aber das macht hier so keinen Sinn, weil Aufgabe zwingend eine Instanz von Gasübernahme braucht, d.h. jeder Konstruktor ohne Gasübernahme macht keinen Sinn. Aber überladene Konstruktoren sind ja nichts seltenes.


----------



## Jw456 (14. Jul 2021)

Ja aber nur tihs welcher von den beiden wird denn genommen?
Ich würde den nicht benutzen löschen um sicher du sein das der richtige benutzt wird.


----------



## Jw456 (14. Jul 2021)

> Oder benutze Gasübernahme.this nicht nur this im sicher zugehen das du das richtige übergibst.


Wollte damit nur sicher stellen das in der Task Klasse auch der richtige construcktor benutzt wird.


> Die Instanz ist da schon verfügbar, aber die Initialisierung ist halt noch nicht durch. Dadurch kann es zu Problemen kommen a.la. eine Instanzvariable ist noch nicht initialisiert aber es wird bereits drauf zugegriffen und Du bekommst eine NPE.


Und genau das wird er haben.


----------



## kneitzel (14. Jul 2021)

Jw456 hat gesagt.:


> Ja aber nur tihs welcher von den beiden wird denn genommen?


Wenn eine Gasübernahme als Parameter angegeben wird (so wie in dem gezeigten Code), dann wird der Konstruktor mit der Gasübernahme genommen. Wenn eine Instanz von Gaszufuhr angegeben wird (in der Klasse wird es vermutlich auch einen ähnlichen Code geben), dann wird der andere Konstruktor genommen.

Wenn Du dir die main in Gasübernahme anschaust, dann wirst Du sehen, dass die Erstellung einer neuen Instanz auskommentiert wird. Daher wird der Fehler nicht durch den geposteten Code kommen... Daher meine Antwort. Darauf sollte der TE erst einmal reagieren. Weitere Schritte sind an der Stelle nicht notwendig.


----------



## Chefselber (14. Jul 2021)

Nabend, 

kneitzel  hatte Recht, ich habe vergessen den Aufruf aus "Gaszufuhr" (ähnlich zu Gasübernahme) - vorerst- auszukommentieren.

Exception in thread "Timer-1" java.lang.NullPointerException: Cannot invoke "Moka7Demo.Gasübernahme.Einlesen()" because "this.gasübernahme" is null
at Moka7Demo.Aufgabe.run(Aufgabe.java:56)
at java.base/java.util.TimerThread.mainLoop(Timer.java:556)
at java.base/java.util.TimerThread.run(Timer.java:506)

Warum hier der Fehler Richtung Gasübernahme zeigt, erschliesst sich mir nicht ganz. 

Erstmal Danke für eure Mühen, hat mir sehr geholfen. Sehr lehrreich. 

Übergaben mit this verwende ich gerne, auch bei ähnlichen Kontruktoren.


----------

