I have a class constructor and I need to perform a clone. From what I've read the best choice is to use a copy constructor, just like in C++. However, I've got an issue. If my "regular" constructor throws exceptions and such exceptions aren't even possible in a "copy constructor" how to I implement a try-catch if the first statement must be this.
public class X
{
public X() throws MyException
{
}
public X(final X original)
{
try {
this();
} catch (MyException e)
{
}
}
}
Is the only option add throws MyException to copy constructor?
Copy all data to a new instance by constructor could look like this:
public class X
{
// some Fields....
int a, b, c;
public X() { }
public X(final X originalX) throws InvalidArgumentException
{
if(originalX == null) {
throw new InvalidArgumentException("originalX should not be null!");
}
this.a = originalX.getA();
//...
}
// getter-setter....
}
And it´s called like this in main() or where ever else:
// x_1 is filles with Data...
X x_2;
try {
x_2 = new X(x_1);
} catch(InvalidArgumentException ex) {
LOG.reportError(ex.getMessage());
x_2 = new X(); // prevent NullPointer for usage afterwards
}
Related
I have some code like so:
public class Foo {
private int x;
public Foo() {
}
public Foo(int x) {
try {
//do some initialisation stuff like:
this.x = x;
}
catch(Exception ge){
//call empty constructor not possible
//this();
//this.EMPTY();
//Foo();
}
}
public static final Foo EMPTY = new Foo();
}
I'd like to know if it is possible to achieve something such as this (I know that calling another constructor must be the first statement in the constructor).
I have looked around here on SO but haven't found anything as such, leading me to believe that perhaps, I ought to handle the error logic in the instantiating method.
Just change the execution order :
public class Foo {
Integer i;
public Foo() {
System.out.println("Empty constructor invoked");
}
public Foo(Integer i) {
this(); //can be omitted
try {
System.out.println("i initialized to : "+i.toString());
} catch (Exception ex) {
System.out.println("i NOT initialized ");
}
}
public static void main(String[] args) {
new Foo(); //prints: Empty constructor invoked
new Foo(5);//prints: Empty constructor invoked
//prints: i initialized to : 5
new Foo(null);//prints: Empty constructor invoked
//prints: i NOT initialized
}
}
In general, it isn't great practice to call code which could throw in a constructor, and worse then suppress the exception from the caller altogether. However, what you could do is refactor your code so that you move the 'default' initialization of the parameterless constructor into a helper method, which you can then call from your exception handler in the second constructor:
public class Foo {
private int x;
public Foo() {
doDefaultInitialize();
}
public Foo(int x) {
try {
// dodgy code which could throw
}
catch(Exception ge){
doDefaultInitialize();
}
}
private void doDefaultInitialize() {
// Fallback initialization goes here
x = 42;
}
}
As you said
calling another constructor must be the first statement in the
constructor
There are 2 solution I usually use when I need this behavior:
Make an init function and call it from both places:
public class Foo {
private int x;
public Foo() {
init();
}
public Foo(int x) {
try {
//do some initialisation stuff like:
this.x = x;
}
catch(Exception ge){
init();
}
}
private init() {
//Do the default initialization here...
}
public static final Foo EMPTY = new Foo();
}
Make a static function to initialize the object and return it.
public class Foo {
private int x;
private Foo() {
this.x = 42;
}
private Foo(int x) throws Exception {
//do some initialization stuff like:
this.x = x;
}
public static Foo getNewInstance(int x) {
try {
return new Foo(x);
} catch (Exception e) {
return new Foo();
}
}
public static final Foo EMPTY = getNewInstance();
}
Just do nothing in the catch block in the constructor. It should work as you want.
However, do have a look at this try-catch-in-constructor-recommended-practice for choosing the right approach to your problem.
Also, if you are doing any default initializations, then follow the approach mentioned by #StuartLC
I was trying to have a handleException method, which can take an exception object and a list of acceptable exception classes to check if the exception is acceptable and can be retried.
void handleException(Exception e, String... acceptableExceptionNames)
throws MyException {
boolean isRetryable = false;
for(String acceptableExceptionName: acceptableExceptionNames) {
try {
if (Class.forName(acceptableExceptionName).isInstance(e)) {
isRetryable = true;
break;
}
} catch (ClassNotFoundException e1) {
continue;
}
}
if (isRetryable) {
// log retryable
} else {
// log error
}
throw new MyException(isRetryable, "Failed");
}
The parameter I pass in is a String... classNames instead of Class<? extends Exception> classes, because if I do something like this:
void handleException(
Exception e,
Class<? extends Exception>... acceptableExceptions)
throws MyException {
for (Class acceptableException : acceptableExceptions) {
if (e instanceOf acceptableException) {}
}
}
The IDE will complain about unknown class acceptableException
Anyone knows if there's a way to pass Class<?>? Or a better way to avoid using String classNames and Class.forName()?
acceptableExceptions isn't a Class, it's a Class[]. You can keep your original design, though, and just use the Class objects directly instead of creating them from strings:
void handleException
(Exception e, Class<? extends Exception>... acceptableExceptionNames)
throws MyException {
boolean isRetryable = false;
for(Class<?> acceptableExceptionName: acceptableExceptionNames) {
if (acceptableExceptionName.isInstance(e)) {
isRetryable = true;
break;
}
}
if (isRetryable) {
// log retryable
} else {
// log error
}
throw new MyException(isRetryable, "Failed");
}
EDIT:
As a side note, this code can be made considerably shorter using Java 8's streams:
void handleException
(Exception e, Class<? extends Exception>... acceptableExceptionNames)
throws MyException {
boolean isRetryable =
Arrays.stream(acceptableExceptionNames).anyMatch(x -> x.isInstance(e));
if (isRetryable) {
// log retryable
} else {
// log error
}
throw new MyException(isRetryable, "Failed");
}
You don't want to check if e is an instance of a Class[], which is what acceptableExceptions is, but if it is an instance of one of the classes referenced by the acceptableExceptions array.
To do that, you need to iterate them, and you need to use the reflection method Class.isInstance(Object obj). As the javadoc says:
This method is the dynamic equivalent of the Java language instanceof operator.
To prevent compiler warnings, you also need to add #SafeVarargs to you method if it is static or final. Otherwise, you need to add #SuppressWarnings("unchecked") to both the method and it's caller(s).
#SuppressWarnings("unchecked")
void handleException(Exception e, Class<? extends Exception>... acceptableExceptions) throws MyException {
boolean acceptable = false;
for (Class<? extends Exception> acceptableException : acceptableExceptions)
if (acceptableException.isInstance(e)) {
acceptable = true;
break;
}
if (acceptable) {
// code here
}
}
In my opinion, it's easier to do if by performing the simple String Comparisons like this:
private void handleException(Exception ex, String... acceptableException) {
for (int x = 0; x < acceptableException.length; x++) {
String[] exceptionClass = ex.getClass().toString().split(".");
if (!acceptableException[x]
.equals(exceptionClass[exceptionClass.length - 1])) {
/* Exception Not Acceptable */
}
}
/* Exception Acceptable */
}
Use following checking
for (Class<? extends Exception> exceptionClass : acceptableExceptions) {
if (exceptionClass.isInstance(e)) {
// it is your exception
}
}
I don't know how to describe the question exactly, sorry!
I have a class(E) base on a base class(B) , and in a helper class(Printer) ,two same name methods (printIt).
These printIt methods use B or E as parameter, this is static polymorphism.
public class B {
public void printMe(){
System.out.println("i am b");
}
}
public class E extends B {
#Override
public void printMe(){
System.out.println("i am e");
}
}
public class Printer {
public void printIt(B b) {
System.out.println("it is b");
}
// public void printIt(B b) {
// if (b.getClass().equals(B.class)) {
// System.out.println("it is b");
// } else if (b.getClass().equals(E.class)) {
// E e = (E) b;
// printIt(e);
// }
// }
public void printIt(E e) {
System.out.println("it is e");
}
public static void main(String[] args) {
B b = new B();
E e = new E();
B be = e;
System.out.println("------------dynamic polymorphism ---------------");
b.printMe(); //i am b
e.printMe(); //i am e
be.printMe(); //i am e
System.out.println("------------static polymorphism ----------------");
Printer printer = new Printer();
printer.printIt(b); //it is b
printer.printIt(e); //it is e
System.out.println("-------------????????????????? -----------------");
printer.printIt(be); //it is b
}
}
In above code, the last printIt call will use "public void printIt(E e)" method to print " it is b ". But "be" variable is a "E" object in fact , is there a way in "Printer" let java to choice method according to the class of object passed in.
If i switch comments on "printIt(B b)" in above code, i wil get what i want, but is it tedious, because if I add many subclass of "B", i have to add many else if in it.
It Seems to me that you simply don't understand the basic ideas behind polymorphism properly. You were completely on the right track but got lost when writing the the printer class which should look like this:
public class Printer {
public void printIt(B b) {
b.printMe();
}
}
This is a very everyday use of polymorphism that seems to perfectly fill your need?
It is best to avoid these kinds of overloads. Where one parameter is a parent of the other.
It is up to the caller to pick which method gets called, which could easily break encapsulation:
printer.printIt(be); //it is b
printer.printIt((E) be); //it is e
Checking the dynamic type of be incurs extra runtime cost, so it is not done by default.
You could implement it yourself however:
class Printer {
private static final Map<Class<?>, BiConsumer<Printer, ?>> map = new HashMap<>();
private static final BiConsumer<Printer, B> defaultConsumer = (p, b) -> System.out.println("it is b");
static {
for(Method m : Printer.class.getDeclaredMethods()) {
if(m.getName().equals("printIt")) {
Class<?>[] params = m.getParameterTypes();
if(params.length == 1 && !params[0].equals(B.class)) {
map.put(params[0], (p, b) -> {
try {
m.invoke(p, b);
} catch (Exception e) {
// Should never happens
throw new RuntimeException("Invalid method mapping");
}
});
}
}
}
}
#SuppressWarnings("unchecked")
public <T> void printIt(B b) {
((BiConsumer<Printer, T>) map.getOrDefault(b.getClass(), defaultConsumer)).accept(this, (T) b);
}
public void printIt(E e) {
System.out.println("it is e");
}
}
I have the following example in which I am trying to call a method othermethod() of class otherClass from inside the run method. I have created an object of this otherClass class as "obj" and using it to call the method . But it is throwing up NullPointerException.
Please let me know why is so.
package isAlive;
class MyClass
{
static int ans=0;
void counter () throws InterruptedException
{
System.out.println("----------------------------");
synchronized (this){
System.out.println("----entering>>>>"+this+" " +this.getClass().getName());
for (int i=0;i<=10;i++)
{System.out.println(Thread.currentThread()+" "+i);
Thread.sleep(3000);}
System.out.println("----exit>>>>"+this.getClass().getName()); }
}
}
public class staticSync extends Thread
{
MyClass obj;
otherClass oth;
int num;
staticSync(int n)
{
num=n;
}
staticSync(MyClass m,int n)
{
obj= m;
num= n;
}
public void run()
{
try {
// obj.counter();
oth.othermethod();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String ... as)
{try{
// MyClass m1= new MyClass();
// MyClass m2= new MyClass();
staticSync s1= new staticSync(20);
System.out.println("s1--"+s1);
//System.out.println("m1="+m1);System.out.println("m2="+m2);
staticSync s2= new staticSync(15);
System.out.println("s2--"+s2);
staticSync s3= new staticSync(15);
staticSync s4= new staticSync(10);//staticSync s5= new staticSync(m1,10);
s1.start();
s2.start();
}
catch (Exception e)
{}
}
}
class otherClass
{
public synchronized void othermethod()
{
System.out.println("---------------inside othermethod-..>"+this.getClass().getName());
}
}
And the output is :
s1--Thread[Thread-0,5,main]
s2--Thread[Thread-1,5,main]
java.lang.NullPointerException
at isAlive.staticSync.run(staticSync.java:67)
java.lang.NullPointerException
at isAlive.staticSync.run(staticSync.java:67)
Even while using the counter() method i am facing the same problem.
The reason why you're getting a null pointer exception is that you are never assigning a value to oth, and therefore it remains being null from when you declared it.
This
otherClass oth;
^ no value is being assigned
Is basically the same as
otherClass oth = null;
Since it is always null, calling a method from the object throws the error.
I have a function which calls another function in a different class which throws an exception based on the paraameter provided. I want
public class A {
public int f(int p){
{
B obj = new B();
obj.g(p);
}
}
public class B {
public int g(int p)
{
// throws an exception for this value of p
}
}
Is it possible that I can catch the exception in class A itself and handle it ? I can't change the implementation of class B.
Yeah just use a try-catch statement.
public class A {
public int f(int p){
{
B obj = new B();
try {
obj.g(p);
} catch ( /* the exception */ ) {
// handle the exception
}
}
}
public class B {
public int g(int p)
{
// throws an exception for this value of p
}
}