从头认识java-12.6 接口与类型信息(怎么绕过接口直接调用类的所有方法)

这一章节我们来讨论一下接口与类型信息。

在之前的章节里面我们提到接口,父类引用子类对象,然后把方法给缩窄了,但是我们这一章节学习到反射,这个约束就变得没有那么严格。

我们来看看下面的例子:

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

从头认识java-12.6 接口与类型信息(怎么绕过接口直接调用类的所有方法)的相关文章

使用Java的反射功能调用类中的方法

最近一直在搞Java的反射,今天使用反射调用方法时出现了很多问题,主要是没有详细参考官方API.所以走了很多弯路. 所以想把这个例子记下来,供自己也供他人学习. package com.mine.practice.reflect; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * 使用反射调用类中的方法 * @author 2014-11-5 上午10:51:28

java异常处理、字符串、类型信息

这篇笔记记得比较杂,笔者对java的规模也并不是很hold得住,后面会慢慢补充,以下例子基本来自<java编程思想> 一.异常处理 java的理念是结构不佳的的代码不能运行.代码的健壮性来自各个构件的健壮性,我们需要把异常想象成事务,其实它就是能把每一件事都当作了一个事务来处理.一般抛出异常可以这样,throw new NullPointerException,或者可以给他更添加参数throw new NullPointerException("t=null")..详细的概

Java编程思想(十五) —— 类型信息之反射

讲完.class,Class之后,继续. 1)泛化的Class引用 Class也可以加入泛型,加入之后会进行类型检查. 贴一下书上原话,Class<?>优于Class,虽然他们是等价的,Class<?>的好处是碰巧或疏忽使用了一个非具体的类引用.我搞不懂这个所谓非具体是什么? 后面弄懂了,其实<?>作为通配符,就是未知的,直接写结论的话不能写个具体类型吧,作者的意思其实就是说加了泛型的Class就是选择了非具体的版本. 加入泛型的原因是提供编译期间的类型检查,操作失误的

Java编程思想(十四) —— 类型信息RTTI(1)

译者翻译的时候有些奇怪,Runtime type information (RTTI) allows you to discover and use type information while a program is running. 运行时类型信息(原来的翻译没有括号这里面的内容,Runtime type information,简称RTTI,个人觉得这样注释比较好)可以让你在程序运行的时候发现和使用类型信息.后面直接出现RTTI让人疑惑. 1)为什么需要RTTI 之前的多态的例子中: p

Java基础知识强化之集合框架笔记33:Arrays工具类中asList()方法的使用

1. Arrays工具类中asList()方法的使用 1 public static <T> List<T> asList(T... a): 把数组转成集合 注意事项: 虽然可以把数组转成集合,但是集合的长度不能改变. 2. 代码示例: (1) 1 package cn.itcast_03; 2 3 import java.util.Arrays; 4 import java.util.List; 5 6 /* 7 * public static <T> List<

在java中将日期(Date类型的数据)增加或减少一定时间的方法

实现的功能:数据来源一般都是从数据库获取的日期类型数据,本例只介绍获取当前时间后,在当前时间基础上增加15分钟. Date date = new Date();date.setTime(date.getTime() + 15*60*1000);System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(date)); 原文地址:https://www.cnblogs.com/elnimo/p/106

cmd下运行java文件时,找不到或无法加载主类的解决方法

最近再看java,却被一个看似很基础的hellorworld头疼了十几分钟,百度了一下,若你在cmd下编辑及运行.java文件时报错,解决方案如下,如图所示: d盘根目录下的.java文件. 打开cmd,进入d盘根目录进行javac demo.java,如图所示: 这一步是不会报错的,因为只要你的classpath设置成功,不会存在报错问题, 此时我们看到刚刚编译的demo.class已经出现在根目录下. 继续下一步时,我们会发现cmd报错,如图所示: 相信很多刚入门的同学们都遇到了这个问题,百

深入理解Java类型信息(Class对象)与反射机制

深入理解Class对象 RRTI的概念以及Class对象作用 认识Class对象之前,先来了解一个概念,RTTI(Run-Time Type Identification)运行时类型识别,对于这个词一直是 C++ 中的概念,至于Java中出现RRTI的说法则是源于<Thinking in Java>一书,其作用是在运行时识别一个对象的类型和类的信息,这里分两种:传统的"RRTI",它假定我们在编译期已知道了所有类型(在没有反射机制创建和使用类对象时,一般都是编译期已确定其类

Java基础 -- 深入理解Java类型信息(Class对象)与反射机制

一 RTTI概念 认识Claa对象之前,先来了解一个概念,RTTI(Run-Time Type Identification)运行时类型识别,对于这个词一直是 C++ 中的概念,至于Java中出现RTTI的说法则是源于<Thinking in Java>一书,其作用是在运行时识别一个对象的类型和类的信息,这里分两种: 传统的”RTTI”:它假定我们在编译期已知道了所有类型(在没有反射机制创建和使用类对象时,一般都是编译期已确定其类型,如new对象时该类必须已定义好): 反射机制,它允许我们在运