After his girlfriend how to makeup, the right to find her? --- java used reflected little secret

story background

White is a program ape, just graduated two years, recently paid a girlfriend, a colleague introduced. Girlfriend and girlfriends to live together. White girlfriend early in the morning received a telephone, a document yesterday her misplaced his computer bag, hoping to help him to the place she lived, she would like her boss reported today.

Emergency such as fire fighting, in order to give presentations, white and quickly punched a car to his girlfriend's cell, then waited for her in the cell door. 7 am, people such as weaving, and so on for a long time, no see, then phone and was told his girlfriend girlfriends, girlfriend makeup makeup is not down to find him, did not take the phone and asked him to identify good.

 

White knows there is a word especially popular, with one-third of the girls said that now looks, painted in five makeup, looking at the beauty of their own seven. Little friends say the girls make-up in the end how much?

 

This how to do it? White had an idea, the enemy does not move I'm not moving, the enemy a move, I inaction. Then put on his spectacles, holding documents, standing in a prominent position, their own observations came the girls, the poor see the day, the final document will be submitted to a look a bit familiar and a little unfamiliar hands of the girl, to complete the task.

The story reflected java

  Work, white also encountered the same problem, he hoped that the following procedure to print true,

    public static void main(String[] args) throws Exception {
        Set<String> s = new HashSet<String>();
        s.add("foo");
        Iterator<String> it = s.iterator();
        Method m = it.getClass().getMethod("hasNext");
        System.out.println(m.invoke(it));
        }

Operation, given as follows:

Exception in thread "main" java.lang.IllegalAccessException: Class com.javapuzzle.davidwang456.ReflectorTest can not access a member of class java.util.HashMap$HashIterator with modifiers "public final"
    at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
    at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
    at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at com.javapuzzle.davidwang456.ReflectorTest.main(ReflectorTest.java:15)

 

  hasNext way is public, so it is can be accessed anywhere. So why call this method based on reflection it is illegal?

We look at the specifications defined jsl] [https://docs.oracle.com/javase/specs/jls/se12/html/jls-6.html#jls-6.6.1

If a top level class or interface type is declared public and is a member of a package that is exported by a module, then the type may be accessed by any code in the same module, and by any code in another module to which the package is exported, provided that the compilation unit in which the type is declared is visible to that other module (§7.3).
If a top level class or interface type is declared public and is a member of a package that is not exported by a module, then the type may be accessed by any code in the same module.
If a top level class or interface type is declared with package access, then it may be accessed only from within the package in which it is declared.
A top level class or interface type declared without an access modifier implicitly has package access.
A member (class, interface, field, or method) of a reference type, or a constructor of a class type, is accessible only if the type is accessible and the member or constructor is declared to permit access:
If the member or constructor is declared public, then access is permitted.
All members of interfaces lacking access modifiers are implicitly public.
Otherwise, if the member or constructor is declared protected, then access is permitted only when one of the following is true:
Access to the member or constructor occurs from within the package containing the class in which the protected member or constructor is declared.
Access is correct as described in §6.6.2.
Otherwise, if the member or constructor is declared with package access, then access is permitted only when the access occurs from within the package in which the type is declared.
A class member or constructor declared without an access modifier implicitly has package access.
Otherwise, the member or constructor is declared private, and access is permitted if and only if it occurs within the body of the top level type (§7.6) that encloses the declaration of the member or constructor.
An array type is accessible if and only if its element type is accessible.

 

  One of which, if the class or interface without any access modifier in the statement, then it implicitly been given package access control . We look at the situation calls:

1.HashSet called by default HashMap generation mode

 /**
 * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
 * default initial capacity (16) and load factor (0.75).
 */
 public HashSet() {
 map = new HashMap<>();
 }

 

2. Call HashMap.KeyIterator class

 final class KeyIterator extends HashIterator
 implements Iterator<K> {
 public final K next() { return nextNode().key; }
 }

 

hasNext () method, call the parent class HashMap.HashIterator of hasNext () method

 abstract class HashIterator {
 Node<K,V> next; // next entry to return
 Node<K,V> current; // current entry
 int expectedModCount; // for fast-fail
 int index; // current slot
 HashIterator() {
 expectedModCount = modCount;
 Node<K,V>[] t = table;
 current = next = null;
 index = 0;
 if (t != null && size > 0) { // advance to first entry
 do {} while (index < t.length && (next = t[index++]) == null);
 }
 }
 public final boolean hasNext() {
 return next != null;
 }
........
}

  We see HashIterator is HashMap subclass, and did not grant public privileges, access rights under the default is: package access, ie it can be invoked class in the package.

The problem here is not the level of access (access level) of the method, but rather the level of access that type of method is located. Defined type (qualifying type) of this type and the role of a general method call is the same as [JLS 13.1]. In this procedure, the process is selected from a class, and this type is represented by a Class object returned from it.getClass method. This is a dynamic type of iterator (dynamic type), which happens to be a private nested class (nested class) java.util.HashMap.KeyIterator. IllegalAccessException anomaly occurs because the class is not public, it comes from another package: access the package members located in other types of non-public is illegal [JLS 6.6.1]. Whether it is a general access or visit reflected by the above-mentioned prohibitions are valid.

Problem-solving ideas

When using reflection to access a type, representing some accessibility of Class objects. hasNext method is declared in a common type of java.util.Iterator, so it should be used for class object reflected access. After this modification, the program will print out the true

    public static void main(String[] args) throws Exception {
        Set<String> s = new HashSet<String>();
        s.add("foo");
        Iterator<String> it = s.iterator();
        Method m = Iterator.class.getMethod("hasNext");
        System.out.println(m.invoke(it));
        }

Lessons learned

In short, access to other package types of non-members of the public is illegal, even if the member is also declared as public members of a common type as well. This is regardless of whether the members are accessed through reflection, these rules are established.

References:

【1】https://new.qq.com/omn/20190527/20190527A07COH.html?pc

【2】https://docs.oracle.com/javase/specs/jls/se12/html/jls-6.html#jls-6.6.1

[3] java doubts

Guess you like

Origin www.cnblogs.com/davidwang456/p/11607979.html