Know the java-12.6 interface and type information from scratch (how to bypass the interface and call all methods of a class directly)

Original Link: https://my.oschina.net/u/2325575/blog/543722

In this chapter we will discuss interface and type information.

In the previous section we mentioned interfaces, where the parent references subclass objects, and then narrows the method down, but when we learned reflection in this section, this constraint becomes less stringent.

Let's take a look at the following examples:

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() {
	}
}

Our normal code would just like this, directly defining the interface, then pointing to the class that implements it.As is the case above, there are fewer methods.However, let's modify the method:

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() {
	}
}

We have modified the isInstanceOf method to transition down so that we can get all the methods in Man, even the following code:

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() {
	}
}
With the code above, we call all the methods in the class directly, including private methods.

This is fatal for encapsulation, so the service-side code we provide generally hides class information, such as:

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() {
	}
}

We can avoid some of the above problems by implying the implementation of classes in one way and exposing them all as interfaces.


Summary: This chapter mainly talks about the interface and type information, and needs to pay attention to calling classes directly across interfaces.


Thank you for this chapter.

-----------------------------------

Catalog




Reprinted at: https://my.oschina.net/u/2325575/blog/543722

Tags: Java less

Posted on Fri, 13 Sep 2019 15:45:23 -0700 by Cameri