在Java中,嵌套类可以是也可以static不是.如果是static,则它们不包含对包含实例的指针的引用(它们也不再被称为内部类,它们被称为嵌套类).
忘记在static不需要该引用时创建嵌套类会导致垃圾收集或转义分析出现问题.
是否有可能创建一个匿名的内部类static?或者编译器是否自动解决这个问题(它可以,因为不能有任何子类)?
例如,如果我创建一个匿名比较器,我几乎不需要对外部的引用:
Collections.sort(list, new Comparator<String>(){
int compare(String a, String b){
return a.toUpperCase().compareTo(b.toUpperCase());
}
}
Run Code Online (Sandbox Code Playgroud) 当我尝试用javac编译这个类时,我得到一个编译错误,并且没有创建Test.class.
public class Test {
public static void main(String[] args) {
int x = 1L; // <- this cannot compile
}
}
Run Code Online (Sandbox Code Playgroud)
但是当我在Eclipse中创建这个类时,我可以看到Test.class出现在target/classes中.当我尝试使用java.exe从命令行运行此类时,我得到了
线程"main"中的异常java.lang.Error:未解决的编译问题:
类型不匹配:无法从long转换为int
Eclipse是否使用自己的特殊Java编译器来创建损坏的.class?java.exe如何知道.class中的complilation问题?
可能重复:
在Java中使用final关键字可以提高性能吗?
在最后的修改有不同的后果取决于你把它应用到什么在java中.我想知道的是,如果另外它可能有助于编译器创建更高效的字节码.我想这个问题深入探讨了JVM的工作原理以及JVM的具体情况.
那么,根据您的专业知识,请执行以下任何一项帮助编译器,或者您是否仅出于正常的java原因使用它们?
谢谢!
编辑:谢谢你的所有答案!请注意,正如@Zohaib建议的那样,我的问题与此重复.在发布之前我搜索得不够好.我不是删除它,因为你们做出了很好的贡献,但答案可以合并.除非另有说明,否则我会让"投票结束"系统决定.
我正在尝试enum,我发现以下编译并在Eclipse上运行正常(Build id:20090920-1017,不确定编译器版本):
public class SwitchingOnAnull {
enum X { ,; }
public static void main(String[] args) {
X x = null;
switch(x) {
default: System.out.println("Hello world!");
}
}
}
Run Code Online (Sandbox Code Playgroud)
在使用Eclipse编译和运行时,这将"Hello world!"正常打印和退出.
使用javac编译器,这NullPointerException将按预期抛出.
那么Eclipse Java编译器中是否存在错误?
注意:这是关于null的Comparable和Comparator合同的衍生产品
这段代码在Eclipse(20090920-1017)中编译并运行良好
import java.util.*;
public class SortNull {
static <T extends Comparable<? super T>>
Comparator<T> nullComparableComparator() {
return new Comparator<T>() {
@Override public int compare(T el1, T el2) {
return
el1 == null ? -1 :
el2 == null ? +1 :
el1.compareTo(el2);
}
};
}
public static void main(String[] args) {
List<Integer> numbers = new ArrayList<Integer>(
Arrays.asList(3, 2, 1, null, null, 0)
);
Comparator<Integer> numbersComp = nullComparableComparator();
Collections.sort(numbers, numbersComp);
System.out.println(numbers);
// "[null, null, 0, …Run Code Online (Sandbox Code Playgroud) 昨天我在Tomcat 8上部署我的Java 8 webapp后遇到了一个有趣的问题.我不想如何解决这个问题,而是更了解为什么会发生这种情况.但是,让我们从头开始.
我有两个类定义如下:
Foo.java
package package1;
abstract class Foo {
public String getFoo() {
return "foo";
}
}
Run Code Online (Sandbox Code Playgroud)
Bar.java
package package1;
public class Bar extends Foo {
public String getBar() {
return "bar";
}
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,它们在同一个包中,并最终在同一个jar中,我们称之为commons.jar.这个jar是我的webapp的依赖(即在我的webapp的pom.xml中被定义为依赖).
在我的webapp中,有一段代码可以:
package package2;
public class Something {
...
Bar[] sortedBars = bars.stream()
.sorted(Comparator.comparing(Bar::getBar)
.thenComparing(Bar::getFoo))
.toArray(Bar[]::new);
...
}
Run Code Online (Sandbox Code Playgroud)
当它被执行时,我得到:
java.lang.IllegalAccessError: tried to access class package1.Foo from class package2.Something
Run Code Online (Sandbox Code Playgroud)
玩耍和试验我能够通过三种方式避免错误:
将Foo类更改为public而不是package-private;
将Something类的包更改为"package1"(即字面上与Foo和Bar类相同,但物理上不同的是webapp中定义的Something类);
在执行违规代码之前强制加载Foo:
try {
Class<?> fooClass = Class.forName("package1.Foo");
} …Run Code Online (Sandbox Code Playgroud)即使我只改变了我的一个课程,Maven总是重新编译所有课程.我使用这个插件配置:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<staleMillis>1</slateMillis>
<useIncrementalCompilation>true</useIncrementalCompilation>
</configuration>
</plugin>
</plugins>
Run Code Online (Sandbox Code Playgroud)
出现这种情况有mvn compile,mvn package和mvn install.
当然,如果您有10-15个文件,这不是问题.但是,我有超过一千个源文件,需要花费很多时间.
Maven编译器插件是否有一些隐藏设置来重新编译修改后的文件?有没有解决方法?
这段代码在Eclipse中编译,但不在javac中编译:
import java.util.function.Consumer;
public class Test {
public static final void m1(Consumer<?> c) {
m2(c);
}
private static final <T> void m2(Consumer<? super T> c) {
}
}
Run Code Online (Sandbox Code Playgroud)
javac输出:
C:\Users\lukas\workspace>javac -version
javac 1.8.0_92
C:\Users\lukas\workspace>javac Test.java
Test.java:5: error: method m2 in class Test cannot be applied to given types;
m2(c);
^
required: Consumer<? super T>
found: Consumer<CAP#1>
reason: cannot infer type-variable(s) T
(argument mismatch; Consumer<CAP#1> cannot be converted to Consumer<? super T>)
where T is a type-variable:
T extends Object declared …Run Code Online (Sandbox Code Playgroud) 以下代码与Eclipse完美编译,但无法使用javac进行编译:
public class HowBizarre {
public static <P extends Number, T extends P> void doIt(P value) {
}
public static void main(String[] args) {
doIt(null);
}
}
Run Code Online (Sandbox Code Playgroud)
我简化了代码,所以现在根本不使用T. 不过,我没有看到错误的原因.由于某种原因,javac决定T代表Object,然后抱怨Object不符合T的界限(这是真的):
HowBizarre.java:6:不兼容的类型; 推断类型参数java.lang.Number,java.lang.Object不符合类型变量的范围P(T)
发现:
<P,T>无效要求:无效
Run Code Online (Sandbox Code Playgroud)doIt(null); ^
请注意,如果我将null参数替换为非null值,则编译正常.
哪个编译器行为正确,为什么?这是其中之一的错误吗?
这个问题是关于Java的有趣行为:它在某些情况下为嵌套类生成了额外的(非默认的)构造函数.
这个问题也是关于奇怪的匿名类,Java用这个奇怪的构造函数生成.
请考虑以下代码:
package a;
import java.lang.reflect.Constructor;
public class TestNested {
class A {
A() {
}
A(int a) {
}
}
public static void main(String[] args) {
Class<A> aClass = A.class;
for (Constructor c : aClass.getDeclaredConstructors()) {
System.out.println(c);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这将打印:
a.TestNested$A(a.TestNested)
a.TestNested$A(a.TestNested,int)
Run Code Online (Sandbox Code Playgroud)
好.接下来,让构造函数A(int a)私有:
private A(int a) {
}
Run Code Online (Sandbox Code Playgroud)
再次运行程序.接收:
a.TestNested$A(a.TestNested)
private a.TestNested$A(a.TestNested,int)
Run Code Online (Sandbox Code Playgroud)
这也没关系.但是现在,让我们main()以这种方式修改方法(添加类A创建的新实例):
public static void main(String[] args) {
Class<A> aClass = A.class;
for (Constructor c : aClass.getDeclaredConstructors()) {
System.out.println(c); …Run Code Online (Sandbox Code Playgroud) java ×9
eclipse ×4
generics ×3
java-8 ×2
maven ×2
null ×2
compilation ×1
enums ×1
javac ×1
maven-3 ×1
nested-class ×1
optimization ×1
reflection ×1
syntax ×1