2011-08-22 110 views
182

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

+9

另外,也许你可以使用Java 7语言功能,但编译为Java 6字节码? – MatrixFrog

+2

当创建一个新项目时,Android Studio会给你一个通知: “minSdkVersion小于19,你不能使用try-with-resources,但其他的Java 7语言功能很好” –

+1

是的,我知道:)我们终于在我们的项目中使用Java 7。 – Zammbi

回答

162

如果您正在使用的Android 工作室,在Java 7 语言应自动无任何补丁被启用。尝试使用资源需要API Level 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 你可以设置合规性甚至高达到Java 8:

  • 文件→工程结构→模块→(挑模块在第二个窗格)→语言→水平(选择 “7.0 - 钻石,ARM,多抓,等”)

Enabling Java 7 on IntelliJ

这仅允许Java 7个语言功能,你几乎不能从任何东西中受益,因为一半的改进也来自图书馆。你可以使用的功能是那些不依赖于库:

  • 钻石运营商(<>
  • 字符串开关
  • 多扣(catch (Exc1 | Exc2 e)
  • 强调了数字文本(1_234_567
  • 二进制文字(0b1110111

而这些featur ES无法使用尚未

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

...“但” :)事实证明,尽管Android的库1.6目标,Android的源确实包含像接口AutoCloseableCloseable等传统界面做es从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()方法对于基元:Boo lean.compare(),Byte.compare(),Short.compare(),Character.compare(),Integer.compare(),Long.compare()。
  • Currency:.getAvailableCurrencies(),.getDisplayName()(但不 .getNumericCode())
  • BitSet:.previousSetBit(),.previousClearBit(),.valueOf(),.toLongArray()。 toByteArray()
  • Collections:.emptyEnumeration(),.emptyIterator(),.emptyListIterator()
  • AutoCloseable
  • Throwable:.addSuppressed(),.getSuppressed(),和4-参数构造
  • Character:.compare(),.isSurrogate(),.getName(),.highSurrogate(),.lowSurrogate(),.isBmpCodePoint()(但不 .isAlphabetic()和.isIdeographic())
  • 系统:.lineSeparator()
  • java.lang.reflect.Modifier(无证):.classModifiers(),.constructorModifiers(),.fieldModifiers(),.interfaceModifiers(),.methodModifiers()
  • NetworkInterface:.getIndex()。 getByIndex()
  • InetSocketAddress:.getHostString()
  • InetAddress:.getLoopbackAddress()
  • Logger:.getGlobal()
  • ConcurrentLinkedDeque
  • AbstractQueuedSynchronizer:.hasQueuedPredecessors()
  • DeflaterOutputStream:3分的构造与 “syncFlush”。
  • Deflater:.NO_FLUSH,.SYNC_FLUSH,.FULL_FLUSH,.deflate()有4个参数

这基本上就是全部。特别是,NIO 2.0不存在,并且Arrays.asList仍然不是@SafeVarargs。

+0

非常有趣的研究!希望这可以在相当短的时间内引入Android上的官方Java 7支持。 – Natix

+0

您是否认为可以使用inteliJ IDE在JDK 7和Android中开发? –

+2

很好的答案。我希望未来能够很快提供完整的jvm级别支持,'nio2'和其他好东西一定会是一个好消息。 –

70

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

  • 实用的答案

是的,我都试过了。但是,这不是一个很大的考验的相容性(没有简单的方法至少)真正使用的Java 7限于6级绝:

  • 首先我一台机器,没有其他的JDK上安装JDK7安装 - Eclipse和Android的未安装或者:

The 7 is the only installed on this machine

  • 然后我安装了一个全新的Eclipse靛蓝和它实际使用JDK 7(当然,因为这是唯一一个检查,因为这是我选择的那个我会恩惊讶)

The 7 is the only used by this Eclipse

  • 然后我安装了最新版本的Android SDK的(编辑:蜂窝,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的工作,以及其它的应用程序,更复杂和使用SQLite,Listview,SensorCamera,但这只能证明Java 7的兼容性处理似乎已经完成并且与Android一起工作。

那么,是否有人尝试使用优秀的老式Ant来绕过上面看到的Eclipse限制?

  • Theroetical答案

无论如何,SDK被设计成与Java 5或6中使用,如所解释here

我们可能有一些与Java 7一起工作,但它会“不小心”工作。 DEX的构建可能正确与否,一旦建立了DEX,它可能工作与否。这是因为使用不合格的JDK根据定义给出了不可预知的结果。

即使某人已经在普通Java 7下成功构建了Android应用程序,但这并不符合JDK的要求。应用于其他应用程序的相同过程可能会失败,或者由此产生的应用程序可能存在与使用该JDK相关的错误。不建议。

对于那些参与webapps开发的人,这与在Java 5或6下构建的Web应用程序完全相同,只能在仅限于Java 4(例如Weblogic 8)的应用程序服务器下部署。这可能会起作用,但这不是可以推荐用于其他目的而不是尝试的东西。从dalvikvm.com

+1

感谢您的详细审查。所以看起来你不能使用Java 7语言功能,但仍然使用Java 7作为Java 6.希望这个变化很快:) – Zammbi

+0

这是用Eclipse。用Ant,这可能是可能的。我希望有人会做测试,我责怪自己懒得去做:) – Shlublu

+0

Eclipse使用Ant ...... –

38

报价:

DX,包括在Android SDK,通过转换普通的Java编译器编译成另一个类文件格式的Java类(在.DEX格式)

的Java类文件

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

据我所知,只有 invokedynamic加入到JVM字节码Java 7中,剩下的就是兼容到Java 6,Java语言本身不使用 invokedynamic。其他新功能,如开关声明使用字符串 s或多捕获只是syntally糖,并不需要字节码更改。例如,多捕获只是复制捕获 - 块为每个可能的例外。

唯一的问题应该是在Java 7中引入的新类中丢失了Android的,像 AutoCloseable,所以我不知道你是否可以使用尝试 -with资源功能(有人尝试过?)。

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

+2

现在的问题是如何配置这样的Java 7源代码编译为Java 6类文件,特别是在Eclipse中? – yuku

+0

剩下的唯一问题是为什么你会打扰? – Warpzit

+0

@Warpzit更大的问题应该是**为什么开发人员不会打扰所有这些困惑?** – aProgrammer

12

由于Android SDK V15的,与Eclipse 3.7.1一起,Java 7的是支持Android的发展。将源代码兼容性设置为1.7,要求将生成的.class文件兼容性设置为1.7,这会导致Android编译器出现以下错误:

Android需要编译器符合性级别5.0或6.0。取而代之的是“1.7”。请使用Android工具>修复项目属性。

0

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

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

5

为了扩大对@KennyTM上面的回答,如果你的目标4.0.3及以上(的minSdkVersion = 15),你可以使用隐藏的API通过向目标的SDK android.jar添加几个类。

一旦你这样做了,你可以在任何Closeable上使用try-with-resources,并且在你自己的类中实现AutoCloseable。

我做了一个zip文件,其中包含所有需要在android.jar中修改以使这些API可用的类的源代码和二进制文件。你只需要解压缩和二进制文件添加到您的
Android的SDK /平台/ Android的NN /的android.jar

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

另外值得注意的是,在过去几个月中,Elliott Hughes已经向Android树做了一些提交:finished off AutoCloseableadded SafeVarargs,unhidden various APIs,fixed Throwable's protected constructoradded support for version 51 class files in dx。所以,最终有一些进展。

编辑(2014年4月):

随着SDK 19的版本也不再需要用额外的API来修补的android.jar。

最好的方法使用try-与资源Android Studio中为定位4.0.3及以上(的minSdkVersion = 15)的应用程序被添加以下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 
    } 
} 

Android Studio会抱怨试用资源不能用于这个API级别,但我的经验是它可以。该项目将在4.0.3及以上版本的设备上建立并运行。我没有遇到过这个问题,一个已经安装到500k +设备上的应用程序。

Android Studio error

要忽略此警告,以下内容添加到您的lint.xml

<issue id="NewApi"> 
    <ignore regexp="Try-with-resources requires API level 19"/> 
</issue> 
+1

我觉得有趣的是Android Studio代码警告说try-with-resources在API 13中是新的,而我应该使用它。虽然没有时间来实际测试它是否正常工作。 – Zammbi

1

似乎得到这个纯蚂蚁工作是有点杂牌的。

但它的工作对我来说:http://www.informit.com/articles/article.aspx?p=1966024

+1

我找了很久。为了通过过滤文章来减少人们的麻烦,你需要改变android提供的build.xml中的'行你的项目!)。对我来说,它在/opt/android-sdk-update-manager/tools/ant/build.xml –

+0

不,你没有。你可以用'custom_rules.xml'覆盖这些属性,在这里看到我的答案:http://stackoverflow.com/a/24608415/194894 – Flow

1

为了使用Java代码构建7层的功能通过Android的蚂蚁基础构建系统,只需把你在你的项目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>