Why my inner class DO see a NON static variable? - java

Earlier I had a problem when an inner anonymous class did not see a field of the "outer" class. I needed to make a final variable to make it visible to the inner class. Now I have an opposite situation. In the "outer" class "ClientListener" I use an inner class "Thread" and the "Thread" class I have the "run" method and does see the "earPort" from the "outer" class! Why?
import java.io.IOException;
import java.net.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class ClientsListener {
private int earPort;
// Constructor.
public ClientsListener(int earPort) {
this.earPort = earPort;
}
public void starListening() {
Thread inputStreamsGenerator = new Thread() {
public void run() {
System.out.println(earPort);
try {
System.out.println(earPort);
ServerSocket listeningSocket = new ServerSocket(earPort);
Socket serverSideSocket = listeningSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(serverSideSocket.getInputStream()));
} catch (IOException e) {
System.out.println("");
}
}
};
inputStreamsGenerator.start();
}
}

Anonymous inner classes have access to static and instance variables. If you want to have also access to local variables, declare them as final. This is how it works:)

Your anonymous inner class has access to the attributes of the containing object. All inner classes that are not declared static have an implicit accessor.
If you want to prevent this from happening, you can declare a static inner class and instantiate that:
public class ClientsListener {
private int earPort;
// Constructor.
public ClientsListener(int earPort) {
this.earPort = earPort;
}
public void starListening() {
Thread inputStreamsGenerator = new InputStreamsGenerator();
inputStreamsGenerator.start();
}
private static class InputStreamsGenerator extends Thread() {
public void run() {
// no access to earport in next line (can make it a constructor argument)
System.out.println(earPort);
try {
System.out.println(earPort);
ServerSocket listeningSocket = new ServerSocket(earPort);
Socket serverSideSocket = listeningSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(serverSideSocket.getInputStream()));
} catch (IOException e) {
System.out.println("");
}
}
};
}

Related

Loading serialized object

I am beginning java, and started to play with serialization. I wonder if there is any way to write the deserialization function inside the class itself. Let me clarify what I mean: I can deserialize an object (i.e. from class Person) from within another class and it works:
public class Dummy{
...
public static void main(String args[])
{
...
Person father = null;
try {
FileInputStream load = new FileInputStream(saved_file);
ObjectInputStream in = new ObjectInputStream(load);
indiv = (Person) in.readObject();
in.close();
load.close();
} catch (...) { ... }
}
}
But, for being tidy, is it possible to move this inside the Person class as a function? For instance, to do something like this:
public class Person implements Serializable {
private boolean isOrphan = false;
private Person parent;
...
public void load(File saved_file) {
try {
FileInputStream load = new FileInputStream(saved_file);
ObjectInputStream in = new ObjectInputStream(load);
this = (Person) in.readObject(); // Error: cannot assign a value to final variabl this
in.close();
load.close();
} catch (...) { ... }
}
}
And then in the other class just call this:
public class Dummy{
...
public static void main(String args[])
{
...
Person father = null;
father.load(saved_file);
}
}
You can't call an instance method on an instance that doesn't exist yet. Even if your code could compile, you would get a NullPointerException because youĆ¹re calling a method on null.
Make your method static and make it return the deserialized instance. More generally, this is not a variable that you can assign, it's an immutable reference to an object.
public static Person load(File saved_file) {
try (FileInputStream load = new FileInputStream(saved_file);
ObjectInputStream in = new ObjectInputStream(load)) {
return (Person) in.readObject();
} catch (...) { ... }
}
public class Dummy {
public static void main(String args[]) {
Person father = Person.load(saved_file);
}
}
PS: I also added try-catch with resources instead of explicit close() because it's safer.

If a class is loaded multiple times, do its static-members get initialized multiple times?

If a class is loaded multiple times, do its static-members get initialized multiple times?
How do I check for that?
If there are different classloaders involved, then they will be completely separate classes, with separate static fields etc - and each will be initialized separately.
(The simplest way to diagnose this is just to log when you get initialized, of course...)
static {
// Log initialization
}
The code inside static block is executed only once: the first time you make an object of that class or the first time you access a static member of that class (even if you never make an object of that class). This mean its invoked when the class loader loads the class to memory. So its per class loader. If you have multiple class loaders each one will have its own copy of the classes so static block will be invoked by each class loaders. To test this you can put a Sysout in a static block an try and load it using a custom class loader. In the below example the static block will be executed twice. One by the system class loader when we run the static main method and then by our custom class loader.
package sample;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class Sample {
static {
System.out.println("Entered Static Block!!");
}
public static void main(String[] args) {
CustomClassLoader loader = new CustomClassLoader();
try {
Class<?> c = loader.findClass("sample.Sample");
Object o = c.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
class CustomClassLoader extends ClassLoader {
private Map<String, Class<?>> classes = new HashMap<String, Class<?>>();
#Override
public String toString() {
return CustomClassLoader.class.getName();
}
#Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
if (classes.containsKey(name)) {
return classes.get(name);
}
byte[] classData;
try {
classData = loadClassData(name);
} catch (IOException e) {
throw new ClassNotFoundException("Class [" + name
+ "] could not be found", e);
}
Class<?> c = defineClass(name, classData, 0, classData.length);
resolveClass(c);
classes.put(name, c);
return c;
}
private byte[] loadClassData(String name) throws IOException {
BufferedInputStream in = new BufferedInputStream(
ClassLoader.getSystemResourceAsStream(name.replace(".", "/")
+ ".class"));
ByteArrayOutputStream out = new ByteArrayOutputStream();
int i;
while ((i = in.read()) != -1) {
out.write(i);
}
in.close();
byte[] classData = out.toByteArray();
out.close();
return classData;
}
}
The following actions do not cause a class to be loaded:
Referring to a static final primitive field that is known at compile time.
classLoader.getResource(className.replace('.', '/') + ".class")
The following cause a class to be loaded (i.e., the .class file is parsed, and a Class<?> object is created):
Any line of code that refers to the class symbolically e.g. Foo.class
Class.forName(String, false, ClassLoader)
ClassLoader.loadClass(String)
Loading a subclass or array of the class, or initializing a class whose code or method signatures refer to the class.
The following cause a class to be initialized (i.e., the static blocks are executed):
Constructing a new instance
Calling a static method
Getting or setting a static field that is not a compile-time constant.
Class.forName(String, true, ClassLoader) and Class.forName(String)
If you do initialize the class from multiple ClassLoaders, the static blocks are indeed executed multiple times. For example, the following code:
import java.net.URL;
import java.net.URLClassLoader;
public class InitializeClassMultipleTimes {
static class Foo {
static {
System.out.format(" %s initialized by %s%n", Foo.class.getSimpleName(), Foo.class.getClassLoader());
}
public static void foo() {}
}
private static Class<Foo> loadClass() {
System.out.println("Loading class.");
// Load the .class file. This will fail if the class file is gone or has
// the wrong file format.
return Foo.class;
}
private static void initializeClass(Class<?> innerClass) {
System.out.println("Initializing class");
try {
Class.forName(innerClass.getName(), true, innerClass.getClassLoader());
} catch (ClassNotFoundException e) {
throw new IllegalStateException(e);
}
}
public static void main(String... argv) throws ClassNotFoundException {
Class<Foo> fooClass = loadClass();
initializeClass(fooClass);
URLClassLoader myClassLoader = ((URLClassLoader) InitializeClassMultipleTimes.class.getClassLoader());
URL[] urls = myClassLoader.getURLs();
for (int i = 0; i < 2; i++) {
URLClassLoader newClassLoader = new URLClassLoader(urls, null); // parent=bootstrap
System.out.format("%nLoading class using another class loader%n", Foo.class.getSimpleName());
Class<?> fooClassAgain = Class.forName(fooClass.getName(), false, newClassLoader);
initializeClass(fooClassAgain);
}
}
}
produces the following output. Note that you can also run it under strace -f -e file to verify when the .class files are read.
Loading class.
Initializing class
Foo initialized by sun.misc.Launcher$AppClassLoader#73d16e93
Loading class using another class loader
Initializing class
Foo initialized by java.net.URLClassLoader#15db9742
Loading class using another class loader
Initializing class
Foo initialized by java.net.URLClassLoader#7852e922

Accessing static variable from another class

My problem is simple: I need to access variable history (which is declared in class BinaryServer) from another class.I'm using more classes to run this code.It's just simple client and server made of sockets.Client sends to server binary code/text and server translates it to text/binary code and sends it back to client.I can provide all classes if needed.
BinaryServer class
import java.net.*;
import java.util.ArrayList;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import graphics.gui;
public class BinaryServer extends gui implements ActionListener,Runnable
{
private ServerSocket server;
private Socket client;
public String text;
private BufferedReader reader;
public static ArrayList<String> history;
public static String binary_letter;
public static String[] letter;
public static int i;
public static String[] binary;
public static String sendback;
public static void main(String[] args)throws IOException
{
BinaryServer instance=new BinaryServer();
gui.buildframe(310,360,"Binary translator server");
gui.buildpane(300,300,true);
gui.buildbutton(300,20,"Translate");
instance.server(63400);
}
public void server(int port)throws IOException
{
history=new ArrayList<String>(100);
server=new ServerSocket(port);
button.addActionListener(this);
while(true)
{
client=server.accept();
reader=new BufferedReader(new InputStreamReader(client.getInputStream()));
text=reader.readLine();
history.add(text);
message.setText(message.getText()+"\n"+text+": ");
}
}
#Override
public void actionPerformed(ActionEvent e)
{
Thread response=new Thread(new BinaryServer());
if(text.contains("0"))
{
int length=text.length();
letter=new String[length+1];
sendback="";
int begin=-8;
int end=0;
for(i=1;i<=length/8;i++)
{
begin=begin+8;
end=i*8;
binary_letter=text.substring(begin,end);
Libary.translate();
message.setText(message.getText()+letter[i]);
sendback=sendback+letter[0+i];
}
}
else
{
int length=text.length();
letter=new String[length+1];
binary=new String[length+1];
sendback="";
for(i=1;i<=length;i++)
{
letter[i]=text.substring(i-1,i);
Libary.encode();
message.setText(message.getText()+binary[i]);
sendback=sendback+binary[0+i];
}
}
response.start();
}
public void run()
{
try
{
Socket feedback=new Socket("localhost",63403);
PrintWriter writer=new PrintWriter(feedback.getOutputStream(),true);
writer.println(sendback);
feedback.close();
return;
}
catch(IOException exc)
{
System.out.println("");
}
}
}
BinaryHistory class (The one I want access variable from)
public class BinaryHistory
{
public static void main(String[] args)
{
show();
}
public static void show()
{
System.out.println(BinaryServer.history);
}
When I access variable history from class BinaryHistory, it's alway null.
If you only declare the variable, regardless of the type or whether or not it's static, it will get a default value of null.
You have to initialize the variable too:
public static ArrayList<String> history = new ArrayList<>();

thread from static method Java

What I want to do is, pass clientId to ClearSession() and use clientId in run() to call session.loadByLastAccessed(). But the error it throws is...
Service.java:117: non-static variable this cannot be referenced from a static context
at Thread t = new Thread(new ClearSession(clientId)) (since it is inner class)
If I change the class to be static, it will throw an error on session.loadByLastAccessed(entityManager, clientId); since entityManager is non-static.
Any ideas on how to start() a thread from a static method and pass a non-static variable?
This is my code...
private EntityManager entityManager; //declared within class along with code below.
public static void initClients()
throws SessionServiceException
{
Properties properties = ApplicationConfig.getInstance().getProperties();
Set<Object> keys = properties.keySet();
String clientId = null;
for (Object keyObject : keys)
{
String key = (String)keyObject;
if (key.startsWith(SessionFactory.CLIENT_PREFIX))
{
clientId = StringUtils.substringAfter(key, SessionFactory.CLIENT_PREFIX);
SessionFactory.getSessionIntf(clientId);
}
}
if(!StringUtils.equals("branch", clientId ))
{
Thread t = new Thread(new ClearSession(clientId));
t.start();
}
}
private class ClearSession implements Runnable
{
private String clientId = "";
public ClearSession(String clientId)
{
this.clientId = clientId;
}
public void run()
{
try
{
// Pause for 2 hours
Thread.sleep(7200000);
// get client session
AbstractImpl session = SessionFactory.getSessionIntf(clientId);
session.loadByLastAccessed(entityManager, clientId);
} catch (InterruptedException ie) {
throw ie;
}
}
}
I see now. You have private class, it means it is inner class. By default inner classes implicitly reference outer class's this. Just declare the class as private static class or just move it outside.

How can I create a static final java.net.URL?

My question is simple. I'm trying to make a set of java.net.URLs that are public static final, so that any class can access them from any context, as these URLs won't change during runtime. However, when I try to create them, I get a compiler error telling me that I must catch or declare thrown a java.net.MalformedURLException, but that is impossible outside a method. Is there any way to circumvent such a constructor that throws a non-java.lang Throwable?
Some dummy code below to visualize my problem:
public class Main
{
public static final java.net.URL STATIC_URL = new java.net.URL("http://example.com/");
public static void main(String[] args)
{
GUI gui = new GUI();
gui.setVisible(true);
}
}
public class GUI extends java.awt.Window
{
public GUI()
{
add(new java.awt.Label(Main.STATIC_URL.toString()));
}
}
If you try to compile this, it will tell you that you can't because of line 3. Hence my question.
An "alternative" which I'd prefer to #HosamAly method:
private static final java.net.URL STATIC_URL = makeUrl("http://www.example.com");
public static java.net.URL makeUrl(String urlString) {
try {
return new java.net.URL(urlString);
} catch (java.net.MalformedURLException e) {
return null; //Or rethrow an unchecked exception
}
}
Use a static initializer:
public class Main {
private static final java.net.URL STATIC_URL;
static {
java.net.URL temp;
try {
temp = new java.net.URL("http://www.example.com");
} catch (java.net.MalformedURLException e) {
temp = null;
}
STATIC_URL = temp;
}
}
Note: The usage of a temporary variable is required to avoid a compilation error about assigning to the final static field twice. If the field is not final, the assignment could be done directly.
If you're sure you want to hardwire a URL. Are you sure? java.net.URL is one of the most comprehensively broken classes in the JDK. In regards to use as a "constant", there is DNS lookup involved and it uses a mutable static (albeit one guarded by a security check, if you have a SecurityManager installed).
If it's just one, a static initialiser should be fine.
private static final java.net.URL STATIC_URL;
static {
try {
STATIC_URL = new java.net.URL("http://example.com/");
} catch (java.net.MalformedException exc) {
throw new Error(exc);
}
}
(Note, you can't qualify the static field name with the class name.)
Note: You really do not want a null - throw an error of some sort and stop the class loading. I've made the constant private as it really isn't the sort of thing you want dependencies on.
If you have lots, then a method for the common code and assignment at the site of the definition is appropriate.
private static final java.net.URL STATIC_URL = constantURL("http://example.com/");
private static URL constantURL(String str) {
try {
return new java.net.URL("http://example.com/");
} catch (java.net.MalformedException exc) {
throw new Error(exc);
}
}
Again, no nulls!
The only way I got this to compile is by removing final and using the static initializer block.
/**
*
*/
package com.neurologic.example;
import java.net.MalformedURLException;
import java.net.URL;
/**
* #author The Elite Gentleman
* #since 06 December 2011
*
*/
public class StaticUrlTest {
public static URL url = null;
static {
try {
url = new URL("http://www.google.com");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}

Categories