这一章节我们来讨论一下接口与类型信息。
在之前的章节里面我们提到接口,父类引用子类对象,然后把方法给缩窄了,但是我们这一章节学习到反射,这个约束就变得没有那么严格。
我们来看看下面的例子:
package com.ray.ch11; public class Test { public static void main(String[] args) { Person man = new Man(); man.sleep(); man.run(); // man.say();//error } } interface Person { public void sleep(); public void run(); } class Man implements Person { public void say() { } @Override public void sleep() { } @Override public void run() { } }
我们一般的代码就会向上面一样,直接定义接口,然后接口指向实现的类。一般的情况就像上面一样,方法给变少了。但是,我们修改一下方法:
package com.ray.ch11; public class Test { public static void main(String[] args) { Person man = new Man(); man.sleep(); man.run(); // man.say();//error if (man instanceof Man) { Man man2 = (Man) man; man2.say(); } } } interface Person { public void sleep(); public void run(); } class Man implements Person { public void say() { } @Override public void sleep() { } @Override public void run() { } }
我们修改了一下,通过isInstanceOf方法,来向下转型,这样我们就可以得到Man里面所有的方法,甚至是下面的代码:
package com.ray.ch11; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class Test { public static void main(String[] args) { try { Class<?> manClass = Class.forName("com.ray.ch11.Man"); Man man = (Man) manClass.newInstance(); Method[] methods = man.getClass().getDeclaredMethods(); for (Method method : methods) { System.out.println(method.getName()); } Method sayMethod = manClass.newInstance().getClass() .getDeclaredMethod("say"); sayMethod.setAccessible(true); sayMethod.invoke(man); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } } interface Person { public void sleep(); public void run(); } class Man implements Person { private void say() { System.out.println("method say"); } @Override public void sleep() { } @Override public void run() { } }
通过上面的代码,我们直接调用类里面所有的方法,包括私有方法。
这个对于封装来说是比较致命的,因此,我们提供的服务端代码一般都隐藏了类的信息,例如:
package com.ray.ch11; public class Test { public static Person makePerson() { return new Man(); } public static void main(String[] args) { Person person = makePerson(); } } interface Person { public void sleep(); public void run(); } class Man implements Person { private void say() { System.out.println("method say"); } @Override public void sleep() { } @Override public void run() { } }
我们通过一个方法隐含了类的实现,全部是以接口的形式对外展现,这样就可以避免了上面的一些问题。
总结:这一章节主要讲述了接口与类型信息的内容,需要注意跨过接口直接调用类的情况。
这一章节就到这里,谢谢。
-----------------------------------
时间: 2024-10-28 23:15:28