I created my own throwable exception but when i want to throw it, the editor says, that a reference to an enclosing class required. I don't know, what i need to write.
Here's code:
public class Main {
int i = 0;
public Main() {
if (i == 0) throw new MyException("i must not be 0"); //Here it says about enclosing class
}
public static void main(String[] args) throws Exception {
new Main();
}
public class MyException extends Exception {
public MyException(String e) {
super(e);
}
}
}
Someone can tell me, where and what i must write?
You've defined MyException as an inner class of Main, then created an instance of it with no corresponding instance of Main available (since the main method is a static method).
You need to declare the exception class separately, outside of Main. Changing the access from public to package-private would let you keep the declaration in the same file. Otherwise, since you can have only one public class per file, it would need to go in its own file.
Alternatively you can define this as a static inner class, like so:
public class Main {
int i = 0;
public static void main(String[] args) throws Exception {
if (i == 0) throw new MyException("i must not be 0"); //Here it says about enclosing class
}
static class MyException extends Exception {
public MyException(String e) {
super(e);
}
}
}
Making the class static means it does not refer to an instance of the enclosing class.
Either declare MyException class as static
public static class MyException extends Exception {
public MyException(String e) {
super(e);
}
}
Or declare it in its own compilable .java file.
The way you have it now, MyException is an inner class of Main which requires an instance of Main to be initialized.
throw new Main().new MyException("i must not be 0");
After your edit, obviously everything works...
This is a general problem: Your class MyException is a nested class to your Main class, and it will always hold a reference to its enclosing instance. You want to make that exception class static, too.
Alternatively, in general but probably not in this case, you can instantiate the inner class using an instance of the outer class:
Main m = new Main();
throw m.new MyException();
Yes, that’s a new after the dot.
Related
I have an abstract class called Trader which acts like a client with a server (StockMarket) and I would like to declare in the Trader class that all classes that inherit from it will need to implement a main entry point so that they can be run.
The problem is that if I write:
public static abstract void main(String[] args) throws Exception;
it gives an error that only visibility modifiers are allowed. But if I remove the static modifier then it does not work as a main entry point allowing it to be run.
So how to declare all subclasses of an abstract class must implement a main method?
You can't.
What I would do instead is declare an abstract, non-static method in Trader:
public abstract void run(String[] args) throws Exception;
And then declare a separate main class that would instantiate an instance, and call the run method:
class RunTrader {
private static final String DEFAULT_CLASS = "...";
public static void main(String[] args) {
try {
String className = System.getProperty("main-trader-class", DEFAULT_CLASS);
Class<Trader> traderClass = (Class<Trader>)Class.forName(className);
Trader trader = traderClass.newInstance();
trader.run(args);
} catch (Exception e) {
// handle the exception
}
}
}
Lets start with the meaning of
public static void main (String[] args)...
static
means that this method does require an instance of the class (containing this method). Java virtual machine (JVM) states this as a requirement for the entry point of a program, reason being that the class may have multiple constructors or no default constructor and there is no way for JVM to know how to create object of the class.
public
allows the method to be accessible outside the package (and class obviously), so JVM is free to invoke this method.
main
is the name of the method that JVM looks for in the class, since there could be multiple public static methods.
void
returns nothing. This is the part of the signature that JVM looks for as entry point.
Now lets answer your question in light of this information. Polymorphism is relevant to OOP concept of inheritance and interface implementation, and it irrelevant to static methods.
So the only choice you have is to choose 1 'public static void main' method as the entry point based on the 'args', call other public static methods. However, other methods need not have the same signature.
Static methods cannot be abstract.
Static members data are same for all the objects and derived classes.
Static members can't be overridden by derived class.
Since abstract method need to be defined in derived class it can't be static.
Remove static and try.
static method does not supports polymorphism, so you can't declare it as abstract. but you can declaring an abstract class with abstract methods that #MauricePerry has been proposed. I will come up with how to get the Main class?
you can extract the Main class name from the system property sun.java.command.
truncate the args from the command.
second, truncate the IDE Main class name if present.
here is my implementation you can using:
public abstract class Trader {
protected abstract void run(String... args);
public static void main(String[] args) throws Exception {
runAs(getMainClass(args)).run(args);
}
private static Trader runAs(Class<?> mainClass)
throws IllegalAccessException, InstantiationException {
checking(!Modifier.isAbstract(mainClass.getModifiers())
, () -> "abstract class can't be run: " + mainClass);
checking(Trader.class.isAssignableFrom(mainClass)
, () -> "class is not a " + Trader.class
+ " can't be run: " + mainClass);
return Trader.class.cast(mainClass.newInstance());
}
private static void checking(boolean condition, Supplier<String> message) {
if (!condition) {
throw new IllegalArgumentException(message.get());
}
}
private static Class<?> getMainClass(String... args)
throws ClassNotFoundException {
String command = commandWithoutArgs(args);
String[] classes = command.split("\\s+");
return Class.forName(classes[ classes.length - 1]);
}
private static String commandWithoutArgs(String[] args) {
String command = System.getProperty("sun.java.command");
return command.substring(0, command.length() - argsLength(args)).trim();
}
private static int argsLength(String[] args) {
if (args.length == 0) {
return 0;
}
return Stream.of(args).collect(Collectors.joining(" ")).length() + 1;
}
}
Example
public class Application extends Trader {
#Override
protected void run(String... args) {
System.out.println("Application");
}
}
run the Application using command java Application or run it in IDE.
To run a program JVM find main method like
public static void main(String[] args)
abstract is not used with main method
I'm learning about inheritance and am working with this simple program that has has a superclass and a subclass as shown below. My question isn't specific to this program; however, this is where I've first seen this happen so I'm using it as an example for a more general conceptual question. Why does simply instantiating the class run the constructors and output the contents? My previous understanding was that instantiating the class simply creates the object but it wont do anything.
SuperClass1.java
public class SuperClass1 {
public SuperClass1(){
System.out.println("This is the superclass constructor.");
}
}
SubClass2.java
public class SubClass2 extends SuperClass1
{
public SubClass2()
{
System.out.println("This is the subclass constructor.");
}
}
Main.java
public class Main {
public static void main(String[] args)
{
SubClass2 obj1 = new SubClass2(); // why should this print something?
}
}
Output
This is the superclass constructor.
This is the subclass constructor.
First of all, instantiating an object means calling (and executing) the constructor, that is what it is for.
So, this:
SubClass2 newInstance = <createNewInstance>;
newInstance.<init()>;
is both done by the constructor call new SubClass2() in Java. There is no separation between "constructing" the object and "initialising" its properties.
Furthermore, if you do not explicitly call another constructor of a super class the default constructor (the one without arguments) is automatically called first thing when creating an object of a class. So instantiating an object of the subclass calls the superclass contructor (which prints the first line), and then prints the second line itself.
More in detail, the subclass looks like this behind the scene:
public class SubClass2 extends SuperClass1
{
public SubClass2()
{
super(); // calls the superclass constructor
System.out.println("This is the subclass constructor.");
}
}
Because the constructor you call includes a print statement.
You call the constructor method SubClass2() which has a print statement in it.
The statements are not printed because the class ist loaded, but because an object of that class in instantiated and the constructors are called:
That a class can be loaded without using constructor is demonstrated by the following code:
public class Test {
public static void main(String[] args) {
try {
Class.forName("Test$Inner");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
static class Inner {
static {
System.out.println("static initializer");
}
public Inner() {
System.out.println("inner ctor");
}
}
}
running that program shows that only the static class initializer is called and no constructor.
I have a checked exception named Class1Exception
public class Class1Exception extends Exception {
...
}
I have a class named Class1 whose constructor may throw Class1Exception.
public class Class1 {
public Class1() throws Class1Exception {
...
}
...
}
Now I want to implement thread-safe Singleton pattern for class Class1. Usually I implement Singleton by making constructor private, creating a static final variable of same type as class which also calls the constructor and then have a getInstance method to access it:
public class Class1 {
private static final Class1 INSTANCE = new Class1();
private Class1() throws Class1Exception {
...
}
public static Class1 getInstance() throws Class1Exception {
return INSTANCE;
}
}
Problem is this solution is not working in this case as the constructor is throwing a checked exception. Changing checked exception to unchecked is not an option. What could be the solution?
Just to clarify: The class Class1 cannot handle Class1Exception by itself. This exception is meant to be handled by any code which is calling Class1.
Thanks
You can use static initilizing section:
private static Class1 INSTANCE;
static {
try {
INSTANCE = new Class1();
} catch (Exception e) {
// handle exception catching
}
}
UPD or you can wrap initilization into new method:
private static final Class1 INSTANCE = createInstance();
private static Class1 createInstance() {
try {
return new Class1();
} catch (Exception e) {
// handle exception catching
}
return null;
}
You have a couple of options:
Init your instance in a static block and wrap the constructor call in a try..catch.
static {
// init your instance here
}
Only call the constructor lazily when the getInstance() gets called and handle the exception on every call.
just use a static initializer while rethrowing your exception using ExceptionInInitializerError.
you can look it up here:
click me
contains the following information:
Signals that an unexpected exception has occurred in a static initializer. An ExceptionInInitializerError is thrown to indicate that an exception occurred during evaluation of a static initializer or the initializer for a static variable.
What about lazy initialization?
public class Class1 {
private static Class1 INSTANCE;
private Class1() throws Class1Exception {
...
}
public static Class1 getInstance() {
if(INSTANCE == null) {
try {
INSTANCE = new Class1();
} catch(Exception1 exc) {
...
}
}
return INSTANCE;
}
In my opinion, this is an anti-pattern. Consider using lazy initialization of resources so the exception is thrown when attempting to invoke one of the singleton's methods, instead of in the constructor where it is not clear when or where it will throw. From the Java Language Specification on static initialization:
For static initialization (section 12.4):
A class or interface type T will be initialized immediately before the
first occurrence of any one of the following:
T is a class and an instance of T is created.
T is a class and a static method declared by T is invoked.
A static field declared by T is assigned.
A static field declared by T is used and the field is not a constant variable (§4.12.4).
T is a top level class (§7.6), and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.
I think it would be way more manageable this way, no?
One alternative to the static initializer block is a private static method :
private static final Class1 INSTANCE = initSingleton();
private static Class1 initSingleton() {
Class1 result;
try {
result = new Class1();
} catch (Exception e) {
// handle exception catching
}
return result;
}
One solution is to adopt two stage construction:
Create instance
Continue with construction that may throw
The caller handles any exception before calling Instance() a second time (say in a finally block). Because the class object was successfully created earlier in stage 1, this subsequent call is now able to return a valid instance. Of course, the second stage construction is not complete but the caller does know that through the exception mechanism.
Example C# (soz:) code:
private static volatile Class1 _instance = null;
private static readonly object _sync = new object();
public static Class1 Instance()
{
if (_instance == null)
{
lock (_sync)
{
if (_instance == null)
{
_instance = new Class1();
_instance.Init(); // can throw
}
}
}
return _instance;
}
private class Caller
{
Class1 _class1;
private void LoadClass1()
{
try
{
_class1 = Class1.Instance();
}
catch (Exception ex)
{
// handle exception
}
finally
{
_class1 = Class1.Instance();
}
}
}
I have tracked down an error to line 362 of the java.lang.Class class:
Constructor<T> tmpConstructor = cachedConstructor;
The variable does not seem to get assigned. In the debug expression windows it only says "tmpConstructor cannot be resolved to a variable". The cachedConstructor is not null.
An error is only thrown further down when a the newInstance() function is called:
try {
return tmpConstructor.newInstance((Object[])null);
} catch (InvocationTargetException e) {
Unsafe.getUnsafe().throwException(e.getTargetException());
// Not reached
return null;
}
Context:
Using JSON Plugin with the Struts2 framework to create Java objects from the received JSON.
The field it is trying to parse is a subclass of an abstract class.
On further inspection (thanks to user902838) I was missing that it can't instantiate an abstract class. So I need to find out how it can instantiate subclasses, which is a different question.
Can someone please explain to me why the tmpconstructor is empty?
It's hard to tell without any information about the class you're trying to instantiate or the exception/error you observe, but my best guess would be that the class does not have a nullary constructor. This program exhibits such a problem:
package example;
public class NewInstanceTest {
public NewInstanceTest(String s) {
}
public static void main(String[] args) throws Exception {
Class.forName("example.NewInstanceTest").newInstance();
}
}
The problem can be fixed by adding a nullary constructor:
package example;
public class NewInstanceTest {
/* nullary constructor: */
public NewInstanceTest() {
this("default");
}
public NewInstanceTest(String s) {
}
public static void main(String[] args) throws Exception {
Class.forName("example.NewInstanceTest").newInstance();
}
}
or by removing all non-nullary constructors so that Java will provide a nullary one automatically:
package example;
public class NewInstanceTest {
public static void main(String[] args) throws Exception {
Class.forName("example.NewInstanceTest").newInstance();
}
}
i was trying to run the following code but i am getting error please clarify my doubt
import java.util.*;
class Except
{ public class AlfaException extends Exception{}
public static void main(String[] args)
{
int b;
Scanner s=new Scanner(System.in);
try
{
b=s.nextInt();
}
catch(InputMismatchException ex)
{
try
{
if(('b'> 67)&&('b'<83)){}
}
catch(AlfaException e){
throw new AlfaException("hello");
}
System.out.println("error found");
}
}
}
Except.java:20: non-static variable this cannot be referenced from a static cont
ext
throw new AlfaException("hello");
^
1 error
Static context is a context that runs on class without actual instance of that class. Your main method is static, that means it can only access static variables. However, your AlfaException is not static. Meaning that it will be bound to an instance of Except class - which you do not have.
Therefore you have 2 choises:
Make AlfaException also static: public static class AlfaException extends Exception{}. That will make it reside in static scope so it will be possible to access it from static functions.
Move all the main(...) method logic into non-static context. Create a function called doWork() that is not static, move all the code from main to doWork, and then call it like this:
.
public static void main(String[] args) {
Except instance = new Except();
instance.doWork();
}
Your AlfaException is a non-static inner class of Except, so it can only be instantiated from inside an instance of Except. The main method is static, so doesn't have an enclosing instance.
Change the declaration of AlfaException to:
public static class AlfaException extends Exception{}
and it should work.
There are couple of mistakes:
AlfaException is never thrown in your try-block
AlfaException is a non-static inner class of Except (see other answers)
If you rethrow AlfaException in catch-block, the main needs a throws like this:
public static void main(String[] args) throws AlfaException { ...
import java.util.*;
class Except
{ public static class AlfaException extends Exception{
public AlfaException(String string) {
super();
}
}
public static void main(String[] args) throws AlfaException
{
int b;
Scanner s=new Scanner(System.in);
try
{
System.out.println("Enter the value for b");
b=s.nextInt();
System.out.println("b value is "+b);
}
catch(InputMismatchException ex)
{
if(('b'> 67)&&('b'<83)){}
System.out.println("error found");
}
}
}
output:
Enter the value for b
80b
error found