причуда компилятора Java: поле объявляется в том же классе, все же “не видимом”

SELECT dewey_number, author_last_name,
       COUNT(dewey_number) AS NumOccurrences
FROM book
JOIN author USING (author_id)
GROUP BY dewey_number,author_last_name
HAVING COUNT(dewey_number) > 1

, Если книга author_id может быть пустой тогда, изменяют соединение на:

LEFT OUTER JOIN author USING (author_id)

, Если author_id столбец имеет другое имя в каждой таблице тогда, Вы не можете использовать ИСПОЛЬЗУЯ, использовать НА вместо этого:

JOIN author ON author.id = book.author_id

или

LEFT OUTER JOIN author ON author.id = book.author_id
7
задан meriton - on strike 22 October 2009 в 19:58
поделиться

5 ответов

Try this:

void foo(Object o) {
    Test foo = getClass().cast(o);
    String so = foo.s;
}

[Edit to clarify]:

getClass().cast(o) returns an object of type 'capture#1-of? extends Test' and not Test. So the issue is related to generics and how the compiler treats it. I don't know the details of the spec on generics but given that some compilers (per comments here) do accept your code, then this is either a loop hole in the spec or some of these compilers are not entirely according to spec.

[Last thoughts]: I believe the eclipse compiler is actually (carefully) correct here. The object o may in fact be an extension of Test (and defined in another package) and the compiler has no way of knowing if that is indeed the case or not. So it is treating it as the worst case of an instance of an extension defined in another package. It would have been super correct if adding a final qualifier to class Test would have allowed access to field s, but it does not.

6
ответ дан 6 December 2019 в 19:38
поделиться

Очень странно. По неизвестной для меня причине компилятору eclipse требуется явное приведение:

void foo(Object o) {
    String os = ((Test)getClass().cast(o)).s;
}

Хотя код отлично компилируется без приведения с помощью Sun JDK (я использую версию 1.6.0_16 в GNU / Linux).

0
ответ дан 6 December 2019 в 19:38
поделиться

Фактически почти во всех случаях, за исключением случаев, когда это требуется для Generics, лучше (и безопаснее) использовать оператор приведения Java. Я обсуждал это здесь . Оператор преобразования Java действительно выглядит многословным, но здесь это правильный инструмент.

Замена метода cast оператором отлично компилируется в Eclipse.

public class Test {

    String s;

    void foo(Object o) {
        String os = ((Test) o).s;
    }
}

Я думаю, что alphazero является подходящим вариантом. исправьте здесь , что Eclipse слишком осторожен.

1
ответ дан 6 December 2019 в 19:38
поделиться

Well, let's see. I'd say the compiler can't properly guarantee that foo() will be called by some entity within the package, and therefore can't guarantee that s is visible. For example, add

protected void bar() {
    foo();
}

and then in some subclass Banana in another package

public void quux() { bar(); }

and oops! getClass() yields Banana, which cannot see s.

Edit: In a sense, other.package.Banana doesn't have a field s. If Banana were in the same package, it could still have its own s property, and would have to refer to Test's s via super.

4
ответ дан 6 December 2019 в 19:38
поделиться

I can't reproduce what you are saying. These both compile fine for me without warning, error or anything with javac directly.

WinXP, javac 1.6.0_16


No I tried with eclipse (v3.4.1, Build id: M20080911-1700) and for the first one it says:

The field Test.s is not visible

At least for Compiler Compliance level 1.6 and 1.5. The funny thing being, if you look at the Quick-fix options it lists a Change to 's' resolution. Which of course doesn't solve the problem. So the eclipse compiler and the Quick-fix "generator" seem to have different views on this too ;-)


For Compiler Compliance level 1.4 (as was to be expected) in eclipse for the first one I get

s cannot be resolved or is not a field

and for the second one I get

Type mismatch: cannot convert from Object to Test

If I specify -source 1.4 and target -1.4 in the command line directly javac says for the first one

cannot find symbol

and for the second one I get

incompatible types
2
ответ дан 6 December 2019 в 19:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: