Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Manipulate Java object reference using class constructor

Tags:

java

This was an exam question which I couldn't complete.

How do you get the following java code to print false by only editing code within the MyClass constructor?

public class MyClass{        
    public MyClass(){
    }

    public static void main(String[] args) {            
        MyClass m = new MyClass();
        System.out.println(m.equals(m));
    }
}

You are NOT allowed to override the equals method, or change any of the code within the main method. The code must run without the program crashing.

According to my research, you can't set a Java object reference to null when you instantiate a class. So I'm officially stumped.

like image 728
Haydos Avatar asked Apr 01 '16 20:04

Haydos


People also ask

Can you pass object to a constructor?

A constructor is a member function of a class, while an object is a non primitive data type. Hence, an object is passed to a constructor by its reference and not value.

How do you reference a call object in Java?

The dot ( . ) is used to access the object's attributes and methods. To call a method in Java, write the method name followed by a set of parentheses (), followed by a semicolon ( ; ).


Video Answer


4 Answers

That was tough!!

public MyClass() {
    System.setOut(new PrintStream(new FilterOutputStream(System.out) {
        @Override
        public void write(byte[] b, int off, int len) throws IOException {
            if(new String(b).contains("true")) {
                byte[] text = "false".getBytes();         
                super.write(text, 0, text.length);
            }
            else {
                super.write(b, off, len);
            }
        }
    }, true));
}

Or Paul Boddington's simplified version:

PrintStream p = System.out; 
System.setOut(new PrintStream(p) { 
    @Override
    public void println(boolean b) { 
        p.println(false); 
    }
});

Or AJ Neufeld's even more simple suggestion:

System.setOut(new PrintStream(System.out) { 
    @Override
    public void println(boolean b) { 
        super.println(false); 
    }
});
like image 156
flakes Avatar answered Oct 12 '22 11:10

flakes


Something along these lines, I would guess:

public MyClass() {
    System.out.println(false);
    System.exit(0);
}

EDIT: I found a puzzle very similar to yours in Java Puzzlers, except in that question the only restriction was that you could not override equals, which basically makes the solution to overload it instead and simply return false. Incidentally, my solution above was also given as an alternative answer to that puzzle.

like image 36
arshajii Avatar answered Oct 12 '22 10:10

arshajii


Another solution is

public MyClass() {
    new PrintStream(new ByteArrayOutputStream()).println(true);
    try {
        Field f = String.class.getDeclaredField("value");
        f.setAccessible(true);
        f.set("true", f.get("false"));
    } catch (Exception e) {
    }
}

The first line is needed because it is necessary for the string literal "true" to be encountered in the PrintStream class before the backing array is modified. See this question.

like image 28
Paul Boddington Avatar answered Oct 12 '22 10:10

Paul Boddington


This is my solution

public class MyClass {

    public MyClass() {
        System.out.println("false");

        // New class
        class NewPrintStream extends PrintStream {
            public NewPrintStream(OutputStream out) {
                super(out);
            }

            @Override
            public void println(boolean b) {
                // Do nothing
            }
        }

        NewPrintStream nps = new NewPrintStream(System.out);
        System.setOut(nps);
    }

    public static void main(String[] args) {
        MyClass m = new MyClass();
        System.out.println(m.equals(m));
    }
}

Basically, this is the variation of @fikes solution.

like image 26
djm.im Avatar answered Oct 12 '22 11:10

djm.im