Android 7的Java 7语言功能

时间:2011-08-22 21:45:57

标签: java android bytecode java-7

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

8 个答案:

答案 0 :(得分:164)

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

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

以下仅供参考。


Java 7的一小部分肯定可以用于Android(注意:我只在4.1上测试过)。

首先,您无法使用Eclipse的ADT,因为it is hard-coded只有Java编译器1.5和1.6兼容。您可以重新编译ADT但我发现除了重新编译整个Android之外,没有简单的方法可以做到这一点。

但您不需要使用Eclipse。例如,Android Studio 0.3.2IntelliJ IDEA CE和其他基于javac的IDE支持编译到Android ,您甚至可以使用以下命令设置合规性:

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

Enabling Java 7 on IntelliJ

这只允许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”不包含它们。

关于如何恢复这些方法已经存在 How do I build the Android SDK with hidden and internal APIs available? 问题。您只需要使用我们自定义的替换当前平台的现有“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()。< / LI>
  • Currency :. getAvailableCurrencies(),. getDisplayName()(但不带 .getNumericCode())
  • BitSet:.previousSetBit(),. previousClearBit(),. valueOf(),. toLongArray(),. toByteArray()
  • Collections:。emptyEnumeration(),. emptyIterator(),. emptyListIterator()
  • AutoCloseable
  • Throwable:。addSuppressed(),. getSuppressed()和4参数构造函数
  • Character:。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()
  • Logger:。getGlobal()
  • ConcurrentLinkedDeque
  • AbstractQueuedSynchronizer:。hasQueuedPredecessors()
  • DeflaterOutputStream:带有“syncFlush”的3个构造函数。
  • Deflater:.NO_FLUSH,.SYNC_FLUSH,.FULL_FLUSH,.deflate(),包含4个参数

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

答案 1 :(得分:70)

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

  • 实用答案

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

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

The 7 is the only installed on this machine

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

The 7 is the only used by this Eclipse

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

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

Compatibility is limited to Java 6

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

Eclipse limits itself to level 6 compatibility

所以我有 Hello World 工作,还有其他应用,更复杂并使用SQLiteListviewSensorCamera,但这只能证明Java 7的兼容性处理似乎做得很好并且与Android一起使用。

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

  • Theroetical answer

无论如何,SDK被设计为与Java 5或6一起使用,如here所述。

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

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

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

答案 2 :(得分:38)

来自dalvikvm.com的报道:

  包含在Android SDK中的

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

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

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

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

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

答案 3 :(得分: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工具&gt;修复项目属性。

答案 4 :(得分:5)

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

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

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

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

同样值得注意的是,在过去的几个月里,Elliott Hughes对Android树做了一些提交:finished off AutoCloseableadded SafeVarargsunhidden various APIs,{{3} }和fixed Throwable's protected constructor。所以,最后还是取得了一些进展。

修改(2014年4月):

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

在Android Studio中针对4.0.3及更高版本( minSdkVersion = 15 )的应用使用try-with-resources的最佳方法是将以下compileOptions添加到您的{ {1}}:

build.gradle

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

Android Studio error

要忽略此警告,请将以下内容添加到android { compileSdkVersion 19 buildToolsVersion '19.0.3' defaultConfig { minSdkVersion 15 targetSdkVersion 19 } compileOptions { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 } }

lint.xml

答案 5 :(得分:1)

似乎让这个与纯蚂蚁一起工作有点像kludge。

但它对我有用:http://www.informit.com/articles/article.aspx?p=1966024

答案 6 :(得分:1)

为了在Android基于ant的构建系统的代码构建中使用Java 7功能,只需将以下内容放在项目根目录的custom_rules.xml中:

<强> custom_rules.xml:

<project name="custom_android_rules">
    <property name="java.target" value="1.7" />
    <property name="java.source" value="1.7" />
</project>

答案 7 :(得分:0)

有些人可能对我发现的这个git项目感兴趣,似乎允许在android上运行Java 7。 https://github.com/yareally/Java7-on-Android

但是,如果我在当前项目中添加这个风险,那么风险太大了。所以我会等到谷歌正式支持Java 7。