Java 7与Android的语言function

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

如果您使用的是Android Studio ,则应该自动启用Java 7 语言,而无需任何补丁。 尝试与资源需要API级别19+和NIO 2.0的东西丢失。

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

以下仅为历史利益。


Java 7的一小部分肯定可以与Android一起使用(注意:我只在4.1上testing过)。

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

但是你不需要使用Eclipse。 例如, Android Studio 0.3.2IntelliJ IDEA CE和其他基于javac的IDE支持编译到Android 您甚至可以将遵从性设置为Java 8:

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

在IntelliJ上启用Java 7

这只允许使用Java 7 语言function ,因为图书馆还有一半的改进,所以你几乎不能从中受益。 你可以使用的function是那些不依赖于库:

  • 钻石操作员( <>
  • string开关
  • 多重捕获( catch (Exc1 | Exc2 e)
  • 数字文字下划线( 1_234_567
  • 二进制文字( 0b1110111

而这些function还不能使用:

  • try -with-resources语句 – 因为它需要不存在的接口“java.lang.AutoCloseable”(这可以在4.4+中公开使用)
  • @SafeVarargs注释 – 因为“java.lang.SafeVarargs”不存在

…“yet”:)事实certificate,虽然Android的库的目标是1.6,但是Android源代码包含了像AutoCloseable这样的接口,而像Closeable这样的传统接口inheritance自AutoCloseable(尽pipeSafeVarargs实际上是缺less的)。 我们可以通过反思来确认它的存在。 它们被隐藏,因为Javadoc有@hide标记,导致“android.jar”不包含它们。

现在已经存在问题如何使用隐藏的和内部的API来构buildAndroid SDK? 关于如何让这些方法回来。 您只需要将当前平台的现有“android.jar”引用replace为我们自定义的引用,那么很多Java 7 API就可以使用了(过程与Eclipse相似)检查项目结构→SDK。

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

  • 在ConcurrentModificationException,LinkageError和AssertionErrorexception链接构造函数
  • 用于基元的静态.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(),.lowSurrogate(),.isBmpCodePoint()(但没有 .isAlphabetic()和.isIdeographic())
  • 系统:.lineSeparator()(无证件?)
  • java.lang.reflect.Modifier :.classModifiers(),.constructorModifiers(),.fieldModifiers(),.interfaceModifiers(),.methodModifiers()
  • NetworkInterface :.getIndex(),.getByIndex()
  • InetSocketAddress :.getHostString()
  • InetAddress :.getLoopbackAddress()
  • logging器 :.getGlobal()
  • ConcurrentLinkedDeque
  • AbstractQueuedSynchronizer :.hasQueuedPredecessors()
  • DeflaterOutputStream :“syncFlush”的3个构造函数。
  • Deflater :.NO_FLUSH,.SYNC_FLUSH,.FULL_FLUSH,.deflate()与4个参数

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

编辑:在写这个时候,最新的版本是Android 9和Eclipse Indigo。 事情从那时起就改变了。

  • 实际的答案

是的,我已经尝试过了。 但这不是一个很好的testing,因为兼容性被限制在6级,没有办法(至less没有简单的方法)真正使用java 7:

  • 首先,我在没有安装其他JDK的计算机上安装了JDK7,Eclipse和Android都没有安装:

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

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

7是这个Eclipse唯一使用的

  • 然后,我在编写这篇文章的时候安装了最新版本的Android SDK(编辑:Honeycomb,API13)。 它find了我的JDK 7并正确安装。 ADT也一样。

  • 但是当我尝试编译并运行一个Hello Word Android应用程序时,我感到很惊讶。 兼容性设置为Java 6,无法强制Java 7:

兼容性仅限于Java 6

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

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

所以我有Hello World的工作,以及其他应用程序,更复杂,使用SQLiteListviewSensorCamera ,但这只能certificateJava 7的兼容性处理似乎已经完成,并与Android的工作。

那么,有没有人尝试用好的老ant,绕过上面看到的Eclipse限制?

  • 理论上的答案

无论如何,SDK被devise成与Java 5或者6一起使用,正如这里所解释的那样。

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

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

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

从dalvikvm.com报价:

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

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

据我所知,只有invokedynamic被添加到Java 7的JVM字节码中,其余的与Java 6兼容.Java语言本身不使用invokedynamic 。 其他的新特性,比如使用String或者Multi catchswitch语句,只不过是syntically sugar而已,并不需要改变字节码。 例如,multi catch只是为每个可能的exception复制catch- block。

唯一的问题应该是Java 7中引入的新类在Android中缺less,例如AutoCloseable ,所以我不确定是否可以使用try -with-resources特性(有人试过?)。

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

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

Android需要编译器符合性级别5.0或6.0。 发现'1.7'。 请使用Android工具>修复项目属性。

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

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

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

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

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

编辑(2014年4月):

随着SDK 19的发布,不再需要用额外的API来修补android.jar。

在Android Studio中为目标4.0.3及以上版本( minSdkVersion = 15 )使用try-with-resources的最佳方法是将以下compileOptions添加到您的build.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工作室会抱怨说,尝试与资源不能使用这个API级别,但我的经验是,它可以。 该项目将在4.0.3及以上版本的设备上build立并运行。 我没有遇到任何问题,已经安装到500k +设备的应用程序。

Android Studio错误

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

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

看来,这与纯粹的ant工作是一个混乱。

但它为我工作: http : //www.informit.com/articles/article.aspx?p=1966024

为了在基于Android的ant构build系统的代码构build中使用Java 7特性,只需将以下custom_rules.xml在项目根目录的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> 

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

但是,如果我在目前正在进行的项目中添加这个项目,风险太大了。 所以我会等到Google正式支持Java 7。