Android 7的Java 7语言功能

Dan*_*yan 189 java android bytecode java-7

只是想知道是否有人尝试过使用Android的新Java 7语言功能?我知道Android会读取Java吐出的字节码并将其转换为dex.所以我想我的问题是它能理解Java 7的字节码吗?

ken*_*ytm 166

如果您使用的是Android Studio,则应自动启用Java 7 语言而不添加任何补丁.Try-with-resource需要API级别19+,并且缺少NIO 2.0的东西.

如果您不能使用Java 7功能,请参阅@Nuno关于如何编辑您的答案的答案build.gradle.

以下仅供参考.


Java 7的一小部分当然可以与Android一起使用(注意:我只在4.1上测试过).

首先,您不能使用Eclipse的ADT,因为它是硬编码的,只有Java编译器1.5和1.6兼容.您可以重新编译ADT,但我发现除了重新编译整个Android之外,没有简单的方法可以做到这一点.

但是您不需要使用Eclipse.例如,Android Studio 0.3.2,IntelliJ IDEA CE和其他基于javac的IDE支持对Android进行编译,您可以使用以下方法将符合性设置为Java 8:

  • 文件→项目结构→模块→(在第二个窗格中选择模块)→语言级别→(选择"7.0 - 钻石,ARM,多捕获等")

在IntelliJ上启用Java 7

这只允许Java 7 语言功能,并且您几乎无法从中受益,因为一半的改进也来自库.您可以使用的功能是那些不依赖于库的功能:

  • 钻石运营商(<>)
  • 字符串开关
  • 多次捕获(catch (Exc1 | Exc2 e))
  • 数字文字中的下划线(1_234_567)
  • 二进制文字(0b1110111)

而这些功能不能使用尚未:

  • try-with-resources语句-因为它需要非现有的接口"java.lang.AutoCloseable"(这个可以公开在4.4或以上版本使用)
  • @SafeVarargs注释 - 因为"java.lang.SafeVarargs"不存在

......"还是":)事实证明,尽管Android的图书​​馆的目标是1.6,但Android源码确实包含AutoCloseable等接口,而像Closeable这样的传统接口确实从AutoCloseable继承(尽管SafeVarargs确实缺失了).我们可以通过反思证实它的存在.隐藏它们只是因为Javadoc有@hide标记,导致"android.jar"不包含它们.

已有问题如何构建具有隐藏和内部API的Android SDK?关于如何恢复这些方法.您只需要将现有平台的现有"android.jar"引用替换为我们自定义的引用,然后就可以使用许多Java 7 API(该过程类似于Eclipse中的过程.检查项目结构→SDK.)

除了AutoCloseable之外,(仅)还显示了以下Java 7 库特性:

  • ConcurrentModificationException,LinkageError和AssertionError中的异常链接构造函数
  • 基元的静态.compare()方法:Boolean.compare(),Byte.compare(),Short.compare(),Character.compare(),Integer.compare(),Long.compare().
  • 货币:.getAvailableCurrencies(),. getDisplayName()(但没有 .getNumericCode())
  • BitSet:.previousSetBit(),. previousClearBit(),. valueOf(),. toLongArray(),. toByteArray()
  • 集合:.emptyEnumeration(),. emptyIterator(),. emptyListIterator()
  • AutoCloseable
  • Throwable:.addSuppressed(),. getSuppressed()和4参数构造函数
  • 字符:.compare(),. isSurrogate(),. getName(),. highSurrogate(),. soSurrogate(),. isBmpCodePoint()(但没有 .isAlphabetic()和.isIdeographic())
  • 系统:.lineSeparator()(未记录?)
  • java.lang.reflect.Modifier:.classModifiers(),. costructorModifiers(),. fieldModifiers(),. interfaceModifiers(),. methodModifiers()
  • NetworkInterface:.getIndex(),. getByIndex()
  • InetSocketAddress:.getHostString()
  • InetAddress:.getLoopbackAddress()
  • 记录器:.getGlobal()
  • ConcurrentLinkedDeque
  • AbstractQueuedSynchronizer:.hasQueuedPredecessors()
  • DeflaterOutputStream:带有"syncFlush"的3个构造函数.
  • Deflater:.NO_FLUSH,.SYNC_FLUSH,.FULL_FLUSH,.deflate(),带有4个参数

这基本上都是.特别是,NIO 2.0不存在,而Arrays.asList仍然不是@SafeVarargs.

  • 值得一提的是,在ICS之前(或者直到HoneyComb),Android运行时中不存在"AutoCloseable"接口.所以,即使你使用修补的android.jar,你也会在2.x系统上收到`NoClassDefFoundError`. (4认同)
  • 尝试使用资源现在可以在SDK 19(Android Kitkat)上使用.见http://tools.android.com/recent/androidstudio032released (4认同)
  • 很好的答案.我希望将来很快就能获得全面的jvm级支持,"nio2"和其他好东西肯定会是一个好消息. (2认同)
  • @deviant:这需要修改Dalvik VM,因为Java 8 lambda使用`invokedynamic`,JVM以Java 6为目标不支持. (2认同)
  • 你可能想要添加一个从Android studio 3.2开始的更新,完全支持语言级别7,如果你正在编译KitKat,那么尝试使用资源 (2认同)

Shl*_*blu 70

编辑:在撰写本文时,最新版本是Android 9和Eclipse Indigo.从那以后,事情发生了变化.

  • 实际答案

是的,我试过了.但这不是一个很好的测试,因为兼容性仅限于6级,没有办法(至少没有简单的方法)真正使用java 7:

  • 首先,我在没有安装其他JDK的机器上安装了JDK7 - 还没有安装Eclipse和Android:

7是这台机器上唯一安装的

  • 然后我安装了一个全新的Eclipse Indigo并检查它实际上是使用JDK 7(好吧,因为这是唯一的一个,因为这是我选择的那个我会感到惊讶)

这是Eclipse唯一使用的7

  • 然后我安装了最新版本的Android SDK(EDIT:Honeycomb,API13,在撰写本文时).它找到了我的JDK 7并正确安装.ADT也一样.

  • 但是在尝试编译和运行Hello Word Android应用程序时,我有一个惊喜.兼容性设置为Java 6,无法强制它使用Java 7:

兼容性仅限于Java 6

  • 我试过一个非Android项目,一个普通的Java项目,我有解释.兼容性级别似乎受到Eclipse的限制(请参阅下图中底部的消息):

Eclipse将自身限制为6级兼容性

因此,我不得不的Hello World的工作,以及其它的应用程序,更复杂和使用SQLite,Listview,SensorCamera,但是这只能证明的Java 7的兼容性处理似乎做得很好,与Android合作.

那么,是否有人尝试使用优秀的旧Ant,以绕过上面提到的Eclipse限制?

  • 理论上的答案

无论如何,SDK被设计成与Java 5或6一起使用,作为解释在这里.

我们可能会使用Java 7,但它会"偶然"工作.DEX的构建可以正常工作,一旦DEX构建,它可能工作与否.这是因为使用非限定JDK会根据定义给出不可预测的结果.

即使有人在普通Java 7下成功构建了一个Android应用程序,但这并不符合JDK的要求.应用于另一个应用程序的相同过程可能会失败,或者生成的应用程序可能存在与该JDK的使用相关的错误.不建议.

对于那些参与webapps开发的人来说,这与在Java 5或6下构建的Web应用程序在仅适用于Java 4的应用程序服务器下部署完全相同(例如,使用Weblogic 8).这可能有用,但这不是可以推荐用于其他目的而不是尝试.

  • 另请注意,如果您使用多个版本的Java玩弄提供的工具不兼容.我的意思是,如果您首先使用java 6工具使用jarsigner签署您的应用程序,然后安装java 7并使用java 7附带的jarsigner签署我们的应用程序的新版本,并且与之前签名相同的密钥库将不匹配! (2认同)

And*_*ndi 38

来自dalvikvm.com的报价:

包含在Android SDK中的dx将由常规Java编译器编译的Java类的Java类文件转换为另一种类文件格式(.dex格式)

这意味着.java源文件并不重要,它只是.class字节码.

据我所知,只有invokedynamic被添加到Java 7中的JVM字节码中,其余部分与Java 6兼容.Java语言本身不使用invokedynamic.其他新功能,如使用Stringswitch语句或multi- catch只是合成糖,不需要更改字节代码.例如,multi- catch只为每个可能的异常复制catch -block.

唯一的问题应该是Android中缺少Java 7中引入的新类,比如AutoCloseable,所以我不确定你是否可以使用try -with-resources功能(有人试过吗?).

对此有何评论?我错过了什么吗?

  • 现在的问题是我们如何配置Java 7源代码编译成Java 6类文件,特别是在eclipse中? (2认同)
  • @Warpzit他唯一的问题是"**Android能理解java 7吗?**"无知永远不是解决方案/答案...... (2认同)

Hos*_*Aly 12

从Android SDK v15开始,与Eclipse 3.7.1一起,Android开发支持Java 7 .将源兼容性设置为1.7要求将生成的.class文件兼容性设置为1.7,这会导致Android编译器出现以下错误:

Android需要编译器合规性级别5.0或6.0.找到'1.7'而不是.请使用Android工具>修复项目属性.


Nun*_*ces 5

要扩展@KennyTM的上述答案,如果您的目标是4.0.3及更高版本(minSdkVersion = 15),则可以通过向目标的SDK android.jar添加几个类来使用隐藏的API.

完成此操作后,您可以在任何Closeable上使用try-with-resources,并在您自己的类中实现AutoCloseable.

我创建了一个zip,其中包含需要在android.jar中修改的所有类的源代码和二进制文件,以使这些API可用.你只需要解压缩它并将二进制文件添加到你的
android-sdk/platforms/android-NN/android.jar

你可以从这里下载:http://db.tt/kLxAYWbr

另外值得注意的是,在过去几个月里,Elliott Hughes已经对Android树做了一些提交:完成了AutoCloseable,添加了SafeVarargs,隐藏了各种API,修复了Throwable的受保护构造函数,在dx中添加了对51版类文件的支持.所以,最后还是取得了一些进展.

编辑(2014年4月):

随着SDK 19的发布,不再需要使用附加API修补android.jar.

对于面向4.0.3及更高版本(minSdkVersion = 15)的应用,在Android Studio中使用try-with-resources的最佳方法是将以下内容添加compileOptionsbuild.gradle:

android {
    compileSdkVersion 19
    buildToolsVersion '19.0.3'

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 19
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
}
Run Code Online (Sandbox Code Playgroud)

Android Studio会抱怨try-with-resources不能与此API级别一起使用,但我的经验是它可以.该项目将在4.0.3及更高版本的设备上构建和运行而不会出现问题.我已经没有遇到任何问题,已经安装到500k +设备中的应用程序.

Android Studio错误

要忽略此警告,请将以下内容添加到lint.xml:

<issue id="NewApi">
    <ignore regexp="Try-with-resources requires API level 19"/>
</issue>
Run Code Online (Sandbox Code Playgroud)