Javaでちゃんと数字も表示されるFizzBuzz書いた

数字も表示されてないのは、やっぱFizzBuzzとして失格だと思うので、ちゃんと数字が表示されるようにがんばりました。
実行したらこうなります。ちゃんと数字が出てます!(追記:でも間違ってる!)

Exception in thread "main" java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:601)
	at javaapplication1.FizzBuzzNewClass.main(FizzBuzzNewClass.java:18)
Caused by: java.lang.StackOverflowError
略
	at 8911.fizzbuzz(FizzBuzzNewClass.java:80)
	at 8910.number(FizzBuzzNewClass.java:32)
	at 8909.number(FizzBuzzNewClass.java:40)
	at 8908.fizz(FizzBuzzNewClass.java:58)
	at 8907.number(FizzBuzzNewClass.java:34)
	at 8906.buzz(FizzBuzzNewClass.java:75)
	at 8905.fizz(FizzBuzzNewClass.java:56)
	at 8904.number(FizzBuzzNewClass.java:34)
	at 8903.number(FizzBuzzNewClass.java:40)
	at 8902.fizz(FizzBuzzNewClass.java:58)
	at 8901.buzz(FizzBuzzNewClass.java:69)
	at 8900.number(FizzBuzzNewClass.java:38)
	at 8899.fizz(FizzBuzzNewClass.java:58)
	at 8898.number(FizzBuzzNewClass.java:34)
	at 8897.number(FizzBuzzNewClass.java:40)
	at 8896.fizzbuzz(FizzBuzzNewClass.java:92)
	at 8895.number(FizzBuzzNewClass.java:32)
	at 8894.number(FizzBuzzNewClass.java:40)
略


ソース

package javaapplication1;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.InputStream;

public abstract class FizzBuzzNewClass{

    public static void main(String[] args) throws Exception {
        Class cls = getNumberedClass(1);
        Object o = cls.newInstance();
        cls.getMethod("number", int.class).invoke(o, 1);
    }
    
    abstract public void number(int i) throws Exception;
    abstract public void fizz(int i) throws Exception;
    abstract public void buzz(int i) throws Exception;
    abstract public void fizzbuzz(int i) throws Exception;
    
    public static class FizzBuzz extends FizzBuzzNewClass{
        public void number(int i) throws Exception{
            Class cls = getNumberedClass(i + 1);
            FizzBuzzNewClass o = (FizzBuzzNewClass) cls.newInstance();
            if(i % 3 == 0){
                if(i % 5 == 0){
                    o.fizzbuzz(i + 1);
                }else{
                    o.fizz(i + 1);
                }
            }else{
                if(i % 5 == 0){
                    o.buzz(i + 1);
                }else{
                    o.number(i + 1);
                }
            }
        }

        public void fizz(int i) throws Exception{
            Class cls = getNumberedClass(i + 1);
            FizzBuzzNewClass o = (FizzBuzzNewClass) cls.newInstance();
            if(i % 3 == 0){
                if(i % 5 == 0){
                    o.fizzbuzz(i + 1);
                }else{
                    o.fizz(i + 1);
                }
            }else{
                if(i % 5 == 0){
                    o.buzz(i + 1);
                }else{
                    o.number(i + 1);
                }
            }
        }
        public void buzz(int i) throws Exception{
            Class cls = getNumberedClass(i + 1);
            FizzBuzzNewClass o = (FizzBuzzNewClass) cls.newInstance();
            if(i % 3 == 0){
                if(i % 5 == 0){
                    o.fizzbuzz(i + 1);
                }else{
                    o.fizz(i + 1);
                }
            }else{
                if(i % 5 == 0){
                    o.buzz(i + 1);
                }else{
                    o.number(i + 1);
                }
            }
        }
        public void fizzbuzz(int i) throws Exception{
            Class cls = getNumberedClass(i + 1);
            FizzBuzzNewClass o = (FizzBuzzNewClass) cls.newInstance();
            if(i % 3 == 0){
                if(i % 5 == 0){
                    o.fizzbuzz(i + 1);
                }else{
                    o.fizz(i + 1);
                }
            }else{
                if(i % 5 == 0){
                    o.buzz(i + 1);
                }else{
                    o.number(i + 1);
                }
            }
        }
    }
    public static Class getNumberedClass(int i) throws Exception{
        String nm = "javaapplication1/FizzBuzzNewClass$FizzBuzz ".trim();//一緒に置き換えられないように
        //クラス名を表すバイトコード
        ByteArrayOutputStream baosMethodName = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(baosMethodName);
        dos.writeByte(1);
        dos.writeUTF(nm);
        byte[] methodNameData = baosMethodName.toByteArray();

        //置き換え後のクラス名を表すバイトコード
        baosMethodName = new ByteArrayOutputStream();
        dos = new DataOutputStream(baosMethodName);
        dos.writeByte(1);
        dos.writeUTF(i + "");
        byte[] myMethodNameData = baosMethodName.toByteArray();
        
        //クラス名を置き換えつつクラスファイルを読み込み
        InputStream is = FizzBuzzNewClass.class.getResourceAsStream("/" + nm + ".class");
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int matchCount = 0;
        for(int d; (d = is.read()) >= 0;){
            if(d == methodNameData[matchCount]){
                ++matchCount;
                if(matchCount == methodNameData.length){
                    //System.out.println("match!" + i);
                    baos.write(myMethodNameData);
                    matchCount = 0;
                }
                continue;
            }
            if(matchCount > 0){
                baos.write(methodNameData, 0, matchCount);
                matchCount = 0;
            }
            baos.write(d);
        }
        
        //クラスを読み込む
        ClassLoader cl = new MyClassLoader(baos.toByteArray());
        Class c = cl.loadClass("hoge");//ここで与えるクラス名はなんでもいいw
        return c;
    }
    
    public static class MyClassLoader extends ClassLoader{
        byte[] code;
        public MyClassLoader(byte[] code) {
            super(FizzBuzzNewClass.class.getClassLoader());
            this.code = code;
        }
        
        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            return defineClass(null, code, 0, code.length);
        }
    }
}