标签: ecj

为什么 javac 为最终字段插入 Objects.requireNonNull(this) ?

考虑以下类:

class Temp {
    private final int field = 5;

    int sum() {
        return 1 + this.field;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我编译和反编译这个类:

> javac --version
javac 11.0.5

> javac Temp.java

> javap -v Temp.class
  ...
  int sum();
    descriptor: ()I
    flags: (0x0000)
    Code:
      stack=2, locals=1, args_size=1
         0: iconst_1
         1: aload_0
         2: invokestatic  #3   // Method java/util/Objects.requireNonNull:(Ljava/lang/Object;)Ljava/lang/Object;
         5: pop
         6: iconst_5
         7: iadd
         8: ireturn
Run Code Online (Sandbox Code Playgroud)

简单来说,javac编译sum()成这样:

int sum() {
    final int n = 1;
    Objects.requireNonNull(this); // <---
    return n + …
Run Code Online (Sandbox Code Playgroud)

java javac java-8 ecj java-11

38
推荐指数
1
解决办法
970
查看次数

Java8中的模糊过载 - 是ECJ还是javac对吗?

我有以下课程:

import java.util.HashSet;
import java.util.List;

public class OverloadTest<T> extends  HashSet<List<T>> {
  private static final long serialVersionUID = 1L;

  public OverloadTest(OverloadTest<? extends T> other) {}

  public OverloadTest(HashSet<? extends T> source) {}

  private OverloadTest<Object> source;

  public void notAmbigious() {
    OverloadTest<Object> o1 = new OverloadTest<Object>(source);
  }

  public void ambigious() {
    OverloadTest<Object> o2 = new OverloadTest<>(source);
  }
}
Run Code Online (Sandbox Code Playgroud)

这在JDK 7的javac以及eclipse(兼容性设置为1.7或1.8)下编译得很好.但是,尝试在JDK 8的javac下编译,我收到以下错误:

[ERROR] src/main/java/OverloadTest.java:[18,35] reference to OverloadTest is ambiguous
[ERROR] both constructor <T>OverloadTest(OverloadTest<? extends T>) in OverloadTest and constructor <T>OverloadTest(java.util.HashSet<? extends T>) in OverloadTest match …
Run Code Online (Sandbox Code Playgroud)

java eclipse javac jls ecj

15
推荐指数
1
解决办法
755
查看次数

使用eclipse编译器编译时,LocalVariableTypeTable中的奇怪"!*"条目

让我们用Eclipse Mars.2捆绑包中的ECJ编译器编译以下代码:

import java.util.stream.*;

public class Test {
    String test(Stream<?> s) {
        return s.collect(Collector.of(() -> "", (a, t) -> {}, (a1, a2) -> a1));
    }
}
Run Code Online (Sandbox Code Playgroud)

编译命令如下:

$ java -jar org.eclipse.jdt.core_3.11.2.v20160128-0629.jar -8 -g Test.java

成功编译后,让我们检查生成的类文件javap -v -p Test.class.最有趣的是为(a, t) -> {}lambda 生成的合成方法:

  private static void lambda$1(java.lang.String, java.lang.Object);
    descriptor: (Ljava/lang/String;Ljava/lang/Object;)V
    flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
    Code:
      stack=0, locals=2, args_size=2
         0: return
      LineNumberTable:
        line 5: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       1     0     a   Ljava/lang/String;
            0       1 …
Run Code Online (Sandbox Code Playgroud)

java eclipse lambda bytecode ecj

13
推荐指数
1
解决办法
268
查看次数

具有多个匹配目标类型的 lambda 表达式的方法签名选择

我在回答一个问题时遇到了一个我无法解释的场景。考虑这个代码:

interface ConsumerOne<T> {
    void accept(T a);
}

interface CustomIterable<T> extends Iterable<T> {
    void forEach(ConsumerOne<? super T> c); //overload
}

class A {
    private static CustomIterable<A> iterable;
    private static List<A> aList;

    public static void main(String[] args) {
        iterable.forEach(a -> aList.add(a));     //ambiguous
        iterable.forEach(aList::add);            //ambiguous

        iterable.forEach((A a) -> aList.add(a)); //OK
    }
}
Run Code Online (Sandbox Code Playgroud)

我不明白为什么显式键入 lambda 的参数(A a) -> aList.add(a)会使代码编译。此外,为什么它链接到 inIterable而不是in 的重载CustomIterable
对此是否有一些解释或规范相关部分的链接?

注意:iterable.forEach((A a) -> aList.add(a));仅在CustomIterable<T>扩展时编译Iterable<T>(完全重载方法CustomIterable导致歧义错误)


在两者上都得到这个: …

java generics lambda javac ecj

13
推荐指数
1
解决办法
396
查看次数

此代码使用ecj但不使用javac编译.这是ecj,javac或两者中的错误吗?

以下代码创建一个Collector产生UnmodifiableSortedSet:

package com.stackoverflow;

import java.util.Collections;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.stream.Collector;
import java.util.stream.Collectors;

public class SOExample {

    public static <T extends Comparable<T>> Collector<T, ?, SortedSet<T>> toSortedSet() {
        return Collectors.toCollection(TreeSet::new);
    }

    public static <T extends Comparable<T>> Collector<T, ?, SortedSet<T>> toUnmodifiableSortedSet() {
        return Collectors.collectingAndThen(toSortedSet(), Collections::<T> unmodifiableSortedSet);
    }
}
Run Code Online (Sandbox Code Playgroud)

代码在ecj编译器下编译:

$ java -jar ~/Downloads/ecj-3.13.101.jar -source 1.8 -target 1.8 SOExample.java
Picked up _JAVA_OPTIONS: -Duser.language=en -Duser.country=GB
Run Code Online (Sandbox Code Playgroud)

但是在javac下:

$ javac -version
Picked up _JAVA_OPTIONS: -Duser.language=en -Duser.country=GB
javac 1.8.0_73

$ javac SOExample.java
Picked …
Run Code Online (Sandbox Code Playgroud)

java javac ecj

12
推荐指数
1
解决办法
173
查看次数

为什么eclipse java编译器(ecj)不能编译这个?

我有以下代码:

package test;

import java.util.stream.IntStream;

public class A {
    public static void main(String[] args) {
        IntStream.range(0, 10).mapToObj(n -> new Object() {
            int i = n;
        }).mapToInt(o -> o.i).forEachOrdered(System.out::println);
    }
}
Run Code Online (Sandbox Code Playgroud)

使用javac 1.8.0_101编译时,此代码工作正常,并按预期生成数字0到9.

但是当我在Eclipse中使用这段代码时,它会告诉我o.i:

i cannot be resolved or is not a field
Run Code Online (Sandbox Code Playgroud)

执行此操作时产生错误:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
    i cannot be resolved or is not a field

    at test.A.main(A.java:9)
Run Code Online (Sandbox Code Playgroud)

为什么我需要使用javac来编译这段代码?

我如何让Eclipse表现出来?

编辑:

我做了一些测试,只要我不在lambda中创建实例,它就可以在ecj中工作:

package test;

import java.util.Optional;
import java.util.function.Supplier;

public class B …
Run Code Online (Sandbox Code Playgroud)

java javac ecj

10
推荐指数
1
解决办法
528
查看次数

Java 中的 `\u0027\n\u0027` 等于 `'\''` 吗?

我在玩Java Unicode Escapes时无意中发现了以下有趣的奇怪之处。这是我写的代码:

static void main(String... args) {
        /*
         * \u0027 - single quote
         */
        char e = \u0027\n\u0027;
        char f = '\'';

        System.out.println(e == f);
        
        //output: true
}
Run Code Online (Sandbox Code Playgroud)

查看编译后的代码,Java 编译器将它们翻译成相同的字符文字。

char e = '\'';
char f = '\'';
Run Code Online (Sandbox Code Playgroud)

通过什么转换规则e变成了 a'而不是换行符\n

顺便说一句,我在 Windows 11 上使用 Oracle JDK 19。

编辑:这个问题似乎与 Java 编译器未能按照 Java 语言规范工作有关。

编辑:当 Oracle JDK 19 在 JLS 18 模式下运行时,似乎会发生此问题。(我不知道如何正确地说这个)

java eclipse jls unicode-escapes ecj

10
推荐指数
0
解决办法
506
查看次数

在maven构建中使用Eclipse Java Compiler(ecj)

Eclipse使用它自己的编译器(ECJ)来编译Java代码.调试使用Eclipse编译的程序更容易,因为可以立即应用简单的代码更改(通过热代码替换).

另一方面,Maven使用(默认情况下)oracle JDK,它生成不同的字节代码,防止在Eclipse调试会话中替换热代码.

因此,如果我计划调试程序,我想将Eclipse ECJ编译器与我的maven构建一起使用.对我来说一个方便的方式是"ecj"配置文件:

此外,可以在settings.xmlEclipse项目属性中指定配置文件激活.

我的问题是:

  1. 这是正确的方法吗?
  2. 如何配置?
  3. 可以使用maven工具链吗?

java eclipse maven ecj

9
推荐指数
2
解决办法
6052
查看次数

var&lt;T&gt; 在 Java 中有什么作用?

我的一个朋友注意到了

var<Integer> list = new ArrayList<Double>();
Run Code Online (Sandbox Code Playgroud)

在 Java 中有效。事实证明, 的类型list被评估为ArrayList<Double>

使用时var<Integer> list = new ArrayList<>();list就是ArrayList<Object>

我们俩都无法弄清楚泛型类型的var作用,因为它似乎被忽略了。但如果是这样,为什么这首先在语法上是正确的?

java generics var ecj

9
推荐指数
2
解决办法
350
查看次数

方法引用原始类型有害吗?

下面的代码包含对Enum::name(通知无类型参数)的引用.

public static <T extends Enum<T>> ColumnType<T, String> enumColumn(Class<T> klazz) {
    return simpleColumn((row, label) -> valueOf(klazz, row.getString(label)), Enum::name);
}

public static <T, R> ColumnType<T, R> simpleColumn(BiFunction<JsonObject, String, T> readFromJson,
        Function<T, R> writeToDb) {
 // ...
}
Run Code Online (Sandbox Code Playgroud)

Javac在编译期间报告警告:

[WARNING]发现原始类型:java.lang.Enum缺少泛型类java.lang.Enum的类型参数

更改表达式会Enum<T>::name导致警告消失.

但是,Idea会在Enum<T>::name版本上标记以下警告:

可以推断出显式类型参数

反过来,Eclipse(ECJ)没有报告任何一种配方的任何问题.

这三种方法中哪一种是正确的?

一方面原始类型相当令人讨厌.如果你试图放一些其他的类型参数,例如 Enum<Clause>::name会导致编译失败,所以这是一些额外的保护.

另一方面,上面的引用等同于e -> e.name()lambda,这个公式不需要类型参数.

Enviorment:

  • Java 8u91
  • IDEA 15.0.3社区
  • ECJ 4.5.2

javac raw-types java-8 method-reference ecj

8
推荐指数
1
解决办法
480
查看次数