2011-08-22 65 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>