// Code generated by gobind. DO NOT EDIT.

// Java class java.Future is a proxy for talking to a Go program.
//
//   autogenerated by gobind -lang=java classes
package java;

import go.Seq;

public final class Future implements Seq.GoObject, java.util.concurrent.Future {
    static { Java.touch(); }
    
    private final int refnum;
    
    @Override public final int incRefnum() {
          Seq.incGoRef(refnum, this);
          return refnum;
    }
    
    Future(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
    
    public Future() { this.refnum = __New(); Seq.trackGoRef(refnum, this); }
    
    private static native int __New();
    
    public final native java.util.concurrent.Future getFuture();
    public final native void setFuture(java.util.concurrent.Future v);
    
    @Override public native java.lang.Object get() throws java.lang.InterruptedException, java.util.concurrent.ExecutionException;
    /**
     * Use a trailing underscore to override multiple overloaded methods.
     */
    @Override public native java.lang.Object get(long p0, java.util.concurrent.TimeUnit p1) throws java.lang.InterruptedException, java.util.concurrent.ExecutionException, java.util.concurrent.TimeoutException;
}

// Code generated by gobind. DO NOT EDIT.

// Java class java.InputStream is a proxy for talking to a Go program.
//
//   autogenerated by gobind -lang=java classes
package java;

import go.Seq;

public final class InputStream extends java.io.InputStream implements Seq.GoObject {
    static { Java.touch(); }
    
    private final int refnum;
    
    @Override public final int incRefnum() {
          Seq.incGoRef(refnum, this);
          return refnum;
    }
    
    public InputStream() {
        super();
        this.refnum = __NewInputStream();
        Seq.trackGoRef(refnum, this);
    }
    
    private static native int __NewInputStream();
    
    public final native java.io.InputStream getInputStream();
    public final native void setInputStream(java.io.InputStream v);
    
    @Override public native int read() throws java.io.IOException;
}

// Code generated by gobind. DO NOT EDIT.

// Java class java.Object is a proxy for talking to a Go program.
//
//   autogenerated by gobind -lang=java classes
package java;

import go.Seq;

public final class Object extends java.lang.Object implements Seq.GoObject {
    static { Java.touch(); }
    
    private final int refnum;
    
    @Override public final int incRefnum() {
          Seq.incGoRef(refnum, this);
          return refnum;
    }
    
    Object(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
    
    public Object() { this.refnum = __New(); Seq.trackGoRef(refnum, this); }
    
    private static native int __New();
    
    public final native java.lang.Object getObject();
    public final native void setObject(java.lang.Object v);
    
}

// Code generated by gobind. DO NOT EDIT.

// Java class java.Runnable is a proxy for talking to a Go program.
//
//   autogenerated by gobind -lang=java classes
package java;

import go.Seq;

public final class Runnable implements Seq.GoObject, java.lang.Runnable {
    static { Java.touch(); }
    
    private final int refnum;
    
    @Override public final int incRefnum() {
          Seq.incGoRef(refnum, this);
          return refnum;
    }
    
    Runnable(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
    
    public Runnable() { this.refnum = __New(); Seq.trackGoRef(refnum, this); }
    
    private static native int __New();
    
    public final native java.lang.Runnable getRunnable();
    public final native void setRunnable(java.lang.Runnable v);
    
    @Override public native void run();
}

// Code generated by gobind. DO NOT EDIT.

// Java class java.Java is a proxy for talking to a Go program.
//
//   autogenerated by gobind -lang=java classes
package java;

import go.Seq;

public abstract class Java {
    static {
        Seq.touch(); // for loading the native library
        _init();
    }
    
    private Java() {} // uninstantiable
    
    // touch is called from other bound packages to initialize this package
    public static void touch() {}
    
    private static native void _init();
    
    
    
    public static native InputStream newInputStream();
}
