Solutions to exercises from lecture 6 on Reflection ex 1.a-1.c changes are marked as comments in the code private void getMethods(){ testMethods = new ArrayList(); try{ Method[] allMethods = testClass.getDeclaredMethods(); // ex1.b for (Method m : allMethods){ if ( m.getName().startsWith("test") || m.getName().startsWith("check") ){ // ex 1.c // ex 1.a - test that it takes zero arguments if(m.getParameterTypes().length == 0) { // ex 1.b - test that it is public if( Modifier.isPublic( m.getModifiers() ) ) testMethods.add(m); else System.err.println("Method " + m.getName() + " isn't public! it should be!"); } else System.err.println("Method " + m.getName() + " takes arguments! it shouldn't!"); } } }catch(SecurityException whatWasThat){ } } ex 1.d protected void check(int expected, int observed) throws CheckFailure { if(extepted != observed) throw new CheckFailure("Value mismatch: " + observed + " != " + expected); } protected void check(String expected, String observed) throws CheckFailure { if(extepted.compareTo(observed) != 0) throw new CheckFailure("String mismatch: " + observed + " != " + expected); } protected void check(Object expected, Object observed) throws CheckFailure { if(!extepted.equals(observed)) throw new CheckFailure("General mismatch: " + observed + " != " + expected); } The check(int, int) is made so that simple types can be checked for numerical equality. As simple types are not objects, the do not contain any equals method or the like. The check(string, string) is made so that strings can be checked lexicographically. The comparison is based on the Unicode value of each character in the strings. String's equals method seems not to take unicode strings into account. The check(Object, Object) is for the general case, where the equals method is used. ex 1.e In Test.java: import java.lang.annotation.*; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Test { int level() default 0; } New testclass MyTestClass2.java: public class MyTestClass2 extends TestClass{ @Test (level = 1) public void parseInt(){ check("'123' is 123",Integer.parseInt("123")==123 ); } @Test(level = 0) public void parseDouble(){ check("15 is 12.5",Double.parseDouble("15") == 12.5 ); } @Test public void testStringEquality(){ String s = "abc"; check("abc is aBc", s.equalsIgnoreCase("aBc")); } public static void main(String[] args){ System.out.println(UnitTester.testTheClass("dk.itu.oop.lecture6.MyTestClass2", 0)); } } Methods added in UnitTester.java: public static String testTheClass(String name, int testLevel){ try{ UnitTester ut = new UnitTester(); ut.setClass(name); ut.getMethods(testLevel); return ut.performTests(); }catch(Exception uups){ return "Could not find class " + name + "\n" + uups; } } private void getMethods(int testLevel){ testMethods = new ArrayList(); try{ Method[] allMethods = testClass.getMethods(); for (Method m : allMethods){ Test t = m.getAnnotation(Test.class); if ( t!= null && t.level() >= testLevel){ testMethods.add(m); } } }catch(SecurityException whatWasThat){} } //Ex 2.a-g import java.lang.reflect.*; import java.util.*; class ToString { //There are more primitives than listed here, but you get the idea private static Class[] primitiveArray = {int.class, Integer.class, Character.class, String.class}; private static ArrayList primitives = new ArrayList(Arrays.asList(primitiveArray)); public static void main(String args[]) { System.out.println(toString( new Car("Fiat", new Person("Per")) ,3) ); } public static String toString(Object o, int depth) { if (depth < 1) return "..."; // ex 2.g - if we go to deep return... StringBuffer b = new StringBuffer(); try{ Class c = o.getClass(); String className = c.getName(); // ex 2.a - get the name of the class b.append(className+"{ "); Field[] fields = c.getDeclaredFields(); // ex 2.b - get all the fields for(Field f : fields) { if(!Modifier.isStatic(f.getModifiers() ) ) { // ex 2.d - exclude static fields String fieldName = f.getName(); Class typeClass = f.getType(); // ex 2.c - print fields by the form "fieldName: fieldType" String fieldType; f.setAccessible(true); Object value = f.get(o); // ex 2.e String val; if (value == null) { val = "null"; } else if (primitives.contains(typeClass)) { val = value.toString(); } else if (typeClass.isArray() ) { // ex 2.f val ="["; int maxIndex = Math.min( Array.getLength(value), 15 ); for (int j = 0; j< maxIndex; j++){ val+= toString(Array.get(value,j), depth-1); if (j+1 < maxIndex) val+= ","; } val +="]"; } else { val = toString(value, depth-1); // ex 2.g - recursivly visit this class } if (typeClass.isArray() ) { fieldType = typeClass.getComponentType().getName()+"[]"; } else { fieldType = typeClass.getName(); } b.append(fieldName + ": " + fieldType + " = " + val ); // ex 2.c if(f != fields[fields.length-1]) b.append(", "); } } b.append(" }"); return b.toString(); } catch(Exception e){ return b.toString() + e.toString(); } } } // ex 2.h // the whole thing without any comments on part-exercises.. import java.lang.reflect.*; import java.util.*; class ToString2 { //There are more primitives than listed here, but you get the idea private static Class[] primitiveArray = {int.class, Integer.class, Character.class, String.class}; private static ArrayList primitives = new ArrayList(Arrays.asList(primitiveArray)); private static String indents = " "; public static void main(String args[]) { System.out.println(toString( new Car("Fiat", new Person("Per")) ,3) ); } public static String toString(Object o, int depth){ return toString(o, depth, indents); } public static String toString(Object o, int depth, String indent) { if (depth < 1) return "..."; StringBuffer b = new StringBuffer(); try{ Class c = o.getClass(); String className = c.getName(); b.append(className+"{\n"); Field[] fields = c.getDeclaredFields(); for(Field f : fields) { if(!Modifier.isStatic(f.getModifiers() ) ) { String fieldName = f.getName(); Class typeClass = f.getType(); String fieldType; f.setAccessible(true); Object value = f.get(o); String val; if (value == null) { val = "null"; } else if (primitives.contains(typeClass)) { val = value.toString(); } else if (typeClass.isArray() ) { val ="["; int maxIndex = Math.min( Array.getLength(value), 15 ); for (int j = 0; j< maxIndex; j++){ val+= toString(Array.get(value,j), depth-1, indents + indent); if (j+1 < maxIndex) val+= ","; } val +="]"; } else { val = toString(value, depth-1, indents + indent); } if (typeClass.isArray() ) { fieldType = typeClass.getComponentType().getName()+"[]"; } else { fieldType = typeClass.getName(); } b.append(indent + fieldName + ": " + fieldType + " = " + val ); if(f != fields[fields.length-1]) b.append(",\n"); } } b.append(" }"); return b.toString(); } catch(Exception e){ return b.toString() + e.toString(); } } }