我有一个抽象类a,类B是扩展a的具体类。
给B班打电话。getDeclaredMethods()除了返回类B的方法签名外,还返回类A的方法签名,但是JAVA文档在getDeclaredMethods()上说了一些不同的东西。
这包括公共、受保护、默认(包)访问和私有方法,但不包括继承的方法
因此,从上面的文档中,我希望从抽象父类继承的方法foo()不应该从getDeclaredMethods()
调用返回,但我得到的方法foo()是从抽象父类继承的,它是从getDeclaredMethods()
调用返回的。
import java.lang.reflect.*;
public class B extends A {
public static void main(String[] args) throws Exception {
Method[] methods = B.class.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
System.out.println(methods[i]);
}
}
}
abstract class A {
public void foo() {
}
}
谁能给我解释一下这种行为吗。
奇怪之处不在getDeclaredMethods()
——它在B
的类文件中,其主体只调用super。foo()
。
我不完全理解它,但它似乎与foo()
是在包私有超类中声明的公共方法有关。
一些测试用例:
A
package private,foo
public(根据问题):方法在B
A
package private,foo
package private:方法未在B
A
public,foo
public:方法未在B
A
public,foo
package private:在B
我怀疑这个想法是不同包中的第三个类不能“看到”A
,但A. foo()
仍然是public
,所以它应该(?)可以通过B
访问。为了使其可访问,B
需要“重新声明”它。
我不清楚这是否真的是正确的——这个(?)在上面JLS 6.6.1规定(重点):
引用类型的成员(类、接口、字段或方法)或类类型的构造函数,只有在该类型可访问且声明该成员或构造函数允许访问时才可访问
但该代码可以在不同的包中使用:
B b = new B();
b.foo();
出于其他答案列出的原因,有时编译器必须向类文件中添加一些棘手的代码;这可以是字段、构造函数或方法的形式。但是,它总是将这些字段标记为synthetic
。这是它添加的实际修改器,您可以检查该方法是否与该方法合成:
method.isSynthetic()
因此,无论何时获得所有方法,都要使用此方法筛选列表,以仅选择在源代码中实际声明的方法;)
合成代码的其他示例包括:自动添加的默认构造函数,如果您有一个非静态内部类,则对字段中的外部类的引用。
之所以会出现这种情况,是因为超类具有包级别的访问权限。如果将classA
的访问修饰符更改为public
(需要将其放入自己的文件中),则B.class中的额外方法。getDeclaredMethods()
将消失。
(还要注意,在类A
上修改的abstract
是一种转移注意力的方法:当类A
不是抽象时,也会发生同样的事情。)
这是Java编译器中针对反射错误的一个变通方法:尽管foo
是一个公共方法,但它是在包范围的类a
中定义的。您可以对类B
进行反思,找到方法,尝试使用反射调用它,结果得到一个IllegalAccessException
。
编译器将在类B
中生成一个桥接方法,这样您就可以正确地反射调用方法foo
。
如果在A
Afinal
方法中使用foo
方法,这是最好的证明,这使得无法修复此反射错误(无法覆盖该方法)
类A
和B
在包abc
中,类C
在包def
中。类C
尝试在类B
上反射调用方法foo
,该方法是公共的,但失败了,因为它是在非公共类A
中定义的。
线程“main”java中出现异常。lang.IllegalAccessException:Class def。C无法访问abc类的成员。A带有修饰语“公开决赛”
package abc;
public class B extends A {
}
class A {
public final void foo() {
}
}
package def;
import java.lang.reflect.Method;
import abc.B;
public class C {
public static void main(String[] args) throws Exception {
Method m = B.class.getMethod("foo");
m.invoke(new B());
}
}
只需从方法foo
中删除final
关键字即可解决问题,因为编译器随后会在类B
中插入合成桥方法。
本错误报告对此进行了解释:
http://bugs.java.com/view_bug.do?bug_id=6342411
以下程序在运行时失败并出现此错误:
Exception in thread "main" java.lang.IllegalAccessException: Class refl.ClientTest can not access a member of class refl.a.Base with
modifiers "public"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65)
at java.lang.reflect.Method.invoke(Method.java:578)
at refl.ClientTest.main(ClientTest.java:9)
========== test/refl/a/Base.java ==========
1 package refl.a;
2
3 class Base {
4 public void f() {
5 System.out.println("Hello, world!");
6 }
7 }
========== test/refl/a/Pub.java ==========
1 package refl.a;
2
3 public class Pub extends Base {}
========== test/refl/ClientTest.java ==========
1 package refl;
2 import refl.a.*;
3 import java.lang.reflect.*;
4
5 public class ClientTest {
6 public static void main(String[] args) throws Exception {
7 Pub p = new Pub();
8 Method m = Pub.class.getMethod("f");
9 m.invoke(p);
10 }
11 }
该提议是在这些非常罕见的情况下添加桥接方法,以修复反射中的问题,而无需其他预见的修复或解决方法。具体来说,当公共方法从非公共类继承到公共类时,我们将生成一个桥接方法。
问题内容: 有人可以详细说明一下,并解释两种方法之间的区别,以及何时/为什么要在另一种方法上使用 问题答案: 包括 由类本身 声明 的 所有方法,而仅返回公共方法,还返回从基类(此处是from )继承的方法。 在和中的Javadocs中阅读有关它的更多信息。
在Solidity的类型系统里面有一些类型有一些在其它语言中没有的语法。其中之一就是函数类型。但依然,使用var时,可以把函数类型作为本地变量。 contract FunctionSelector { function select(bool useB, uint x) returns (uint z) { var f = a; if (useB) f = b; ret
这是正确的吗? 我可以找到一个相关的问题,但它是有参数的,我不能在没有params的情况下转换它。
特殊包中可用的功能是通用功能,它遵循广播和自动数组循环。 下面来看看一些最常用的特殊函数功能 - 立方根函数 指数函数 相对误差指数函数 对数和指数函数 兰伯特函数 排列和组合函数 伽马函数 下面来简单地了解这些函数。 立方根函数 这个立方根函数的语法是 - 。 这将获取的基于元素的立方体根。 参考下面的一个例子 - 执行上面示例代码,得到以下结果 - 指数函数 指数函数的语法是 - 。 这将计算
关于字符集和替代字形 除键盘上可看到的字符之外,字体中还包括许多字符。根据字体的不同,这些字符可能包括连字、分数字、花饰字、装饰字、序数字、标题和文体替代字、上标和下标字符、变高数字和全高数字。字形是特殊形式的字符。例如,在某些字体中,大写字母 A 有几种形式可用,如花饰字或小型大写字母。 插入替代字形的方式有两种: 可以使用 “字形 ”面板来查看和插入任何字体中的字形。 可以使用 “OpenTy
一些字符在 XML 中有特殊的含义,只能够通过其实体名称输入 字符 写法 缩写涵义 < < less than > > greater than & & ampersand " " quote ' ' apostrophe 空格 none-break space 通常需要使用实体输入的字符包括<、&、空格 XML 会将任意数量的空格解析为一