powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Убейте
5 сообщений из 55, страница 3 из 3
Убейте
    #34116789
bemtaill
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Leonidvhttp://java.sun.com/docs/books/jls/third_edition/html/names.html#36191
Не совсем то, но идет действительно от туда. Во первых у меня в примере ошибка, ну да ладно:))

Короче при A a=new B(); ссылка а видит только интерфейс класса А, а там ни хрена нету, кроме унаследованных полей/методов от Object, т.к. согласно приведенной ссылке если protected и в разных паках, то не видит она метод v(). НО! Если делаем его паблик (он наследуется и становиться видим в интерфейсе класса А) , то при вызове через ссылку типа 'А' согласно положениям позднего связывания вызовется метод класса B.
Разобрался млин.
Спасибо.
...
Рейтинг: 0 / 0
Убейте
    #34116791
02
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
02
Гость
Я тоже хочу поговорить об Этом (начитавшись всякой фигни в JLS)
Имеем две версии класса Class1. Назовем их public и private в соответствии с модификаторами доступа метода v():
Код: plaintext
1.
2.
3.
4.
 package  package1;
 public   class  Class1 {
     public   void  v(){System.out.println("package1.Class1.v()");}
}
Код: plaintext
1.
2.
3.
4.
 package  package1;
 public   class  Class1 {
     private   void  v(){System.out.println("package1.Class1.v()");}
}
Имеем одну версию класса Class2.
Код: plaintext
1.
2.
3.
4.
 package  package2;
 public   class  Class2  extends  package1.Class1 {
      public   void  v() {System.out.println("package2.Class2.v()");}
}
Она благополучно компилируется на любой из версий класса Class1 c одинаковыми class-файлами в результате. Тот факт, что для public-версии Class1 имеет место overriding v(), а для private-версии - нет, компилятор принимает во внимание только в первом случае и только для проверки правил overriding'a. Если правила не соблюдены, результат - compile-time error, как например
Код: plaintext
1.
2.
 class  Class1 { public  Number v(){ return   1 ;}}
 class  Class2  extends  Class1 { public  String v() { return  "";}}
А если
Код: plaintext
1.
2.
3.
4.
5.
 class  Class1 { private  Number v(){ return   1 ;}}
или
 class  Class1 { private  String v(){ return  "1";}}
или
 class  Class1 { public  String v(){ return  "1";}}
то результат для Сlass2.class один и тот же: дескриптор метода v() класса Class2

Далее, имеем одну версию класса Test
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
 package  package2;
 public   class  Test {
     public   static   void  main(String[] args) {        
        package1.Class1 c =  new  Class2();
        c.v();
    }
}
Класс Test компилируется только с public-версией Class1.class
Почему?
Читаем JLS
15.12.1 Compile-Time Step 1: Determine Class or Interface to Search
The first step in processing a method invocation at compile time is to figure out the name of the method to be invoked and which class or interface to check for definitions of methods of that name. There are several cases to consider, depending on the form that precedes the left parenthesis, as follows:
...
If the form is Primary.NonWildTypeArgumentsopt Identifier, then the name of the method is the Identifier. Let T be the type of the Primary expression; then the class or interface to be searched is T if T is a class or interface type, or the upper bound of T if T is a type variable.
...

В нашем случае Primary.NonWildTypeArgumentsopt Identifier == c.v, T == package1.Class1, то есть компилятор ищет метод v() в package1.Class1
Далее
15.12.2 Compile-Time Step 2: Determine Method Signature
The second step searches the type determined in the previous step for member methods. This step uses the name of the method and the types of the argument expressions to locate methods that are both accessible and applicable, that is, declarations that can be correctly invoked on the given arguments...

Находит в public-версии Class1, но не находит в private-версии Class1(compile-time error). В первом случае результат - Test.class, в котором вызов метода с.v() интерпретируется след образом
15.12.3 Compile-Time Step 3: Is the Chosen Method Appropriate?
The following compile-time information is then associated with the method invocation for use at run time:
The name of the method.
The qualifying type of the method invocation (§13.1).
The number of parameters and the types of the parameters, in order. The result type, or void.
The invocation mode, computed as follows:
-If the compile-time declaration has the static modifier, then the invocation mode is static.
-Otherwise, if the compile-time declaration has the private modifier, then the invocation mode is nonvirtual.
-Otherwise, if the part of the method invocation before the left parenthesis is of the form super . Identifier or of the form ClassName.super.Identifier then the invocation mode is super.
-Otherwise, if the compile-time declaration is in an interface, then the invocation mode is interface.
-Otherwise, the invocation mode is virtual.

Здесь The name of the method == v,
The qualifying type of the method invocation == package1.Class1
The invocation mode virtual == invokevirtual - одна из четырех инструкций
JVM Specification 3.11.8 Method Invocation and Return Instructions
The following four instructions invoke methods:
-invokevirtual invokes an instance method of an object, dispatching on the (virtual) type of the object. This is the normal method dispatch in the Java programming language.
-invokeinterface invokes a method that is implemented by an interface, searching the methods implemented by the particular runtime object to find the appropriate method.
-invokespecial invokes an instance method requiring special handling, whether an instance initialization method (§3.9), a private method, or a superclass method.
-invokestatic invokes a class (static) method in a named class.

Теперь стартуем Test.class c Class2.class и public-версией Class1.class и читаем
15.12.4 Runtime Evaluation of Method Invocation
At run time, method invocation requires five steps. First, a target reference may be computed. Second, the argument expressions are evaluated. Third, the accessibility of the method to be invoked is checked. Fourth, the actual code for the method to be executed is located. Fifth, a new activation frame is created, synchronization is performed if necessary, and control is transferred to the method code.
[quot]15.12.4.1 Compute Target Reference (If Necessary)
Сделано: package1.Class1 c = new Class2();
15.12.4.2 Evaluate Arguments
Проехали
15.12.4.3 Check Accessibility of Type and Method
Обсудим позже, но в нашем случае с public-версией Class1 все ОК
15.12.4.4 Locate Method to Invoke
The strategy for method lookup depends on the invocation mode.

If the invocation mode is static, no target reference is needed and overriding is not allowed. Method m of class T is the one to be invoked.

Otherwise, an instance method is to be invoked and there is a target reference. If the target reference is null, a NullPointerException is thrown at this point. Otherwise, the target reference is said to refer to a target object and will be used as the value of the keyword this in the invoked method. The other four possibilities for the invocation mode are then considered.

If the invocation mode is nonvirtual, overriding is not allowed. Method m of class T is the one to be invoked.

Otherwise, the invocation mode is interface, virtual, or super, and overriding may occur. A dynamic method lookup is used. The dynamic lookup process starts from a class S, determined as follows:

-If the invocation mode is interface or virtual, then S is initially the actual run-time class R(Class2) of the target object. This is true even if the target object is an array instance. (Note that for invocation mode interface, R necessarily implements T; for invocation mode virtual, R is necessarily either T or a subclass of T.)
-If the invocation mode is super, then S is initially the qualifying type (§13.1) of the method invocation.

The dynamic method lookup uses the following procedure to search class S, and then the superclasses of class S, as necessary, for method m.

Let X(Class1) be the compile-time type of the target reference of the method invocation.
1. If class S(Class2) contains a declaration for a non-abstract method named m with the same descriptor (same number of parameters, the same parameter types, and the same return type) required by the method invocation as determined at compile time (§15.12.3), then:
- If the invocation mode is super or interface, then this is the method to be invoked, and the procedure terminates.

- If the invocation mode is virtual, and the declaration in S overrides (§8.4.8.1) X.m(Class1.v), then the method declared in S is the method to be invoked, and the procedure terminates.

2. Otherwise, if S has a superclass, this same lookup procedure is performed recursively using the direct superclass of S in place of S; the method to be invoked is the result of the recursive invocation of this lookup procedure.

The above procedure will always find a non-abstract, accessible method to invoke, provided that all classes and interfaces in the program have been consistently compiled. However, if this is not the case, then various errors may occur. The specification of the behavior of a Java virtual machine under these circumstances is given by The Java Virtual Machine Specification.We note that the dynamic lookup process, while described here explicitly, will often be implemented implicitly, for example as a side-effect of the construction and use of per-class method dispatch tables, or the construction of other per-class structures used for efficient dispatch.

Результат: System.out.println("package2.Class2.v()")

Теперь стартуем Test.class c Class2.class и private-версией Class1.class
Все так же, кроме пунктов:
a)
- If the invocation mode is virtual, and the declaration in S overrides (§8.4.8.1) X.m(Class1.v), then the method declared in S is the method to be invoked, and the procedure terminates.
Здесь Class2.v не overrides Class1.v, т.к. Class1.v - private
Поэтому
2. Otherwise, if S has a superclass, this same lookup procedure is performed recursively using the direct superclass of S in place of S; the method to be invoked is the result of the recursive invocation of this lookup procedure.
и вызывается Class1.v
Результат: System.out.println("package1.Class1.v()")
b)

15.12.4.3 Check Accessibility of Type and Method
Let C(Test) be the class containing the method invocation, and let T(Class1) be the qualifying type of the method invocation (§13.1), and m(v) be the name of the method, as determined at compile time (§15.12.3). An implementation of the Java programming language must insure, as part of linkage, that the method m still exists in the type T. If this is not true, then a NoSuchMethodError (which is a subclass of IncompatibleClassChangeError) occurs. If the invocation mode is interface, then the implementation must also check that the target reference type still implements the specified interface. If the target reference type does not still implement the interface, then an IncompatibleClassChangeError occurs.

The implementation must also insure, during linkage, that the type T and the method m are accessible. For the type T:
- If T is in the same package as C, then T is accessible.
- If T is in a different package than C, and T is public, then T is accessible.
- If T is in a different package than C, and T is protected, then T is accessible if and only if C is a subclass of T.

For the method m:
- If m is public, then m is accessible. (All members of interfaces are public (§9.2)).
- If m is protected, then m is accessible if and only if either T is in the same package as C, or C is T or a subclass of T.
- If m has default (package) access, then m is accessible if and only if T is in the same package as C.
- If m is private, then m is accessible if and only if C is T, or C encloses T, or T encloses C, or T and C are both enclosed by a third class. If either T or m is not accessible, then an IllegalAccessError occurs (§12.3)

И вот здесь я не согласен с Ним же
Я лично не считаю это багом. И не понимаю, откуда вы взяли, что такое поведение - баг.

, потому что если в JLS написано: If either T or m is not accessible, then an IllegalAccessError occurs, а ее(IllegalAccessError) не возникает, то такая ситуация, на мой взгляд, называется bug
А так же не согласен с Ним жеА то, что вы не компилите проект (все зависимые пакеты и классы, как того требуется), а только лишь выборочно - это исключительно ваши проблемы, а не java.

, потому что если бы с выходом каждой новой версии JRE Sun просила бы сообщество перекомпилироваться, то это было странноватенько.
Спасибо за внимание
...
Рейтинг: 0 / 0
Убейте
    #34121528
Jozic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
АСУ ТПшниквот кто то уже это дело и до нас обнаружил
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4298813
на другом форуме говорят, что в 1.6 наконец это исправили.
вообще то оригинальный баг здесь http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4030988 и пофикшен он еще в 1.5, но пофикшен специфично :) нужно использовать опцию JVM: -verify
он жеЯ считаю, что это не баг. Потому что это задача не runtime-машины - проверять доступность классов.
Это задача компилятора. Ага, и верификатора, который и должен кидать IllegalAccessError в таком случае
...
Рейтинг: 0 / 0
Убейте
    #34121624
02
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
02
Гость
2Jozic
Спасибо Теперь все стало понятно
Правда -verify, начиная c 1.2, не упоминается ни в command line options, ни в документации
Они предлагают пользоваться -Xfuture
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4337532
...
Рейтинг: 0 / 0
Убейте
    #34121865
Фотография МТД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Jozic
Мда.
Слишком это мутно у них получилось.
Проще перекомпиливать всё и не думать о плохом :)
...
Рейтинг: 0 / 0
5 сообщений из 55, страница 3 из 3
Форумы / Java [игнор отключен] [закрыт для гостей] / Убейте
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]