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.2 , IntelliJ IDEA CE和其他基于javac的IDE支持编译到Android ,您甚至可以将遵从性设置为Java 8:
- 文件→项目结构→模块→(在第二个窗格中select模块)→语言级别→(select“7.0 – 钻石,ARM,多重捕获等”)
这只允许使用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都没有安装:
- 然后,我安装了一个全新的Eclipse Indigo,并检查了它实际上是使用JDK 7(嗯,因为这是唯一一个,因为这是我select的我会感到惊讶)
-
然后,我在编写这篇文章的时候安装了最新版本的Android SDK(编辑:Honeycomb,API13)。 它find了我的JDK 7并正确安装。 ADT也一样。
-
但是当我尝试编译并运行一个Hello Word Android应用程序时,我感到很惊讶。 兼容性设置为Java 6,无法强制Java 7:
- 我尝试了一个非Android项目,一个普通的Java项目,我解释了。 兼容性级别似乎受到Eclipse的限制(请参阅下图中底部的消息):
所以我有Hello World的工作,以及其他应用程序,更复杂,使用SQLite
, Listview
, Sensor
和Camera
,但这只能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 catch的switch语句,只不过是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 +设备的应用程序。
要忽略此警告,请将以下内容添加到您的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。