22

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.

Tunaki
  • 132,869
  • 46
  • 340
  • 423
Haydos
  • 322
  • 1
  • 8

4 Answers4

18

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); 
    }
});
flakes
  • 21,558
  • 8
  • 41
  • 88
  • 2
    @JohnnyWiller I feel clever which is always a sign that I'm overcomplicating things lol – flakes Apr 01 '16 at 21:20
  • 2
    Damn you beat me by a few minutes! You can simplify this a bit. It can just be `final PrintStream p = System.out; System.setOut(new PrintStream(p) { public void println(boolean b) { p.println(false); }});` – Paul Boddington Apr 01 '16 at 21:25
  • 1
    Great answer - I've upvoted. You beat me because I was not aware of `setOut`. I was trying to use `field.set` which doesn't seem to work. – Paul Boddington Apr 01 '16 at 21:32
  • 1
    PrintStream was the one I was working on. Beat me to it. Not quite as clean, but you could just print "false" and then raise an exception to prevent the second line of the main method from being called. It does mean you get a stack trace after false, but it didn't say you had to exit cleanly ;-) – ManoDestra Apr 01 '16 at 21:38
  • 3
    @flkes Further shortening it: `System.setOut(new PrintStream(System.out) { @Override public void println(boolean b) { super.println(false); } });` No need for a `p` variable. – AJNeufeld Apr 01 '16 at 21:39
14

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.

arshajii
  • 127,459
  • 24
  • 238
  • 287
4

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.

Community
  • 1
  • 1
Paul Boddington
  • 37,127
  • 10
  • 65
  • 116
  • You must be loading some static code when you call `println(boolean b)`. very interesting – flakes Apr 02 '16 at 01:32
  • Looks like you need to get Java to `intern()` the `String("true")` into the pool. You can likely get away with doing something like `String t = "true"` to achieve the same effect. – Boris the Spider Apr 02 '16 at 09:56
  • 1
    @BorisTheSpider Weirdly it doesn't work. It seems you have to encounter the *right* `"true"` literal - i.e. the one in the `PrintStream` class. See the linked question for the true extent of how strange this all is. – Paul Boddington Apr 02 '16 at 10:25
1

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.

djm.im
  • 3,295
  • 4
  • 30
  • 45