Các tính năng ngôn ngữ Java 7 với Android


188

Chỉ tự hỏi nếu có ai đã thử sử dụng các tính năng ngôn ngữ Java 7 mới với Android? Tôi biết rằng Android đọc mã byte mà Java phát ra và biến nó thành dex. Vì vậy, tôi đoán câu hỏi của tôi là nó có thể hiểu mã byte của Java 7 không?


10
Ngoài ra, có thể bạn có thể sử dụng các tính năng ngôn ngữ Java 7 nhưng biên dịch sang mã byte Java 6?
MatrixFrog

2
Android Studio hiện sẽ cung cấp cho bạn một thông báo khi tạo một dự án mới: "Với minSdkVersion dưới 19, bạn không thể sử dụng tài nguyên dùng thử, nhưng các tính năng ngôn ngữ Java 7 khác vẫn ổn"
IgorGanapolsky 30/12/13

1
Vâng tôi biết :) Cuối cùng chúng tôi cũng đang sử dụng Java 7 trong dự án của mình.
Daniel Ryan

Câu trả lời:


165

Nếu bạn đang sử dụng Android Studio , ngôn ngữ Java 7 sẽ được bật tự động mà không cần bất kỳ bản vá nào. Thử tài nguyên yêu cầu API cấp 19+ trở lên và nội dung NIO 2.0 bị thiếu.

Nếu bạn không thể sử dụng các tính năng của Java 7, hãy xem câu trả lời của @Nuno về cách chỉnh sửa của bạn build.gradle.

Sau đây chỉ dành cho lợi ích lịch sử.


Một phần nhỏ của Java 7 chắc chắn có thể được sử dụng với Android (lưu ý: Tôi mới chỉ thử nghiệm trên 4.1).

Trước hết, bạn không thể sử dụng ADT của Eclipse vì nó được mã hóa cứng mà chỉ có trình biên dịch Java 1.5 và 1.6 tuân thủ. Bạn có thể biên dịch lại ADT nhưng tôi thấy không có cách nào đơn giản để làm điều đó ngoài việc biên dịch lại toàn bộ Android với nhau.

Nhưng bạn không cần sử dụng Eclipse. Chẳng hạn, Android Studio 0.3.2 , IntelliJ IDEA CE và các IDE dựa trên javac khác hỗ trợ biên dịch cho Android bạn có thể đặt tuân thủ ngay cả lên tới Java 8 với:

  • Tệp → Cấu trúc dự án → Mô-đun → (chọn mô-đun ở khung thứ 2) → Cấp độ ngôn ngữ → (chọn "7.0 - Kim cương, ARM, đa bắt, v.v.")

Kích hoạt Java 7 trên IntelliJ

Điều này chỉ cho phép các tính năng ngôn ngữ Java 7 và bạn khó có thể hưởng lợi từ bất cứ điều gì vì một nửa cải tiến cũng đến từ thư viện. Các tính năng bạn có thể sử dụng là những tính năng không phụ thuộc vào thư viện:

  • Toán tử kim cương ( <>)
  • Chuyển đổi chuỗi
  • Đa bắt ( catch (Exc1 | Exc2 e))
  • Gạch dưới chữ số ( 1_234_567)
  • Chữ nhị phân ( 0b1110111)

Và các tính năng này không thể sử dụng được nêu ra :

  • Câu lệnh try-with-resource - bởi vì nó yêu cầu giao diện không tồn tại "java.lang.AutoClosizable" (điều này có thể được sử dụng công khai trong 4.4+)
  • Chú thích @SafeVarargs - vì "java.lang.SafeVarargs" không tồn tại

... "Chưa" :) Hóa ra, mặc dù thư viện của Android đang nhắm mục tiêu cho 1.6, nhưng nguồn Android có chứa các giao diện như AutoClosizable và các giao diện truyền thống như Closizable thừa hưởng từ AutoClosizable (tuy nhiên SafeVarargs thực sự bị thiếu). Chúng ta có thể xác nhận sự tồn tại của nó thông qua sự phản chiếu. Chúng bị ẩn đơn giản vì Javadoc có @hidethẻ, khiến "android.jar" không bao gồm chúng.

Đã có câu hỏi hiện tại Làm cách nào để xây dựng SDK Android với các API ẩn và nội bộ có sẵn? về cách lấy lại các phương thức đó. Bạn chỉ cần thay thế tham chiếu "android.jar" hiện có của Nền tảng hiện tại bằng nền tảng tùy chỉnh của chúng tôi, sau đó nhiều API Java 7 sẽ có sẵn (quy trình tương tự như trong Eclipse. Kiểm tra cấu trúc dự án → SDK.)

Ngoài bổ sung cho AutoClosizable, (chỉ) các tính năng thư viện Java 7 sau đây cũng được tiết lộ:

  • Các hàm tạo chuỗi ngoại lệ trong ConcurrencyModificationException, LinkageError và AssertsError
  • Các phương thức tĩnh .compare () cho các nguyên hàm: Boolean.compare (), Byte.compare (), Short.compare (), Character.compare (), Integer.compare (), Long.compare ().
  • Tiền tệ : .getAv AvailableCurrencies (), .getDisplayName () (nhưng không có .getNumericCode ())
  • BitSet : .previousSetBit (), .previousClearBit (), .valueOf (), .toLongArray (), .toByteArray ()
  • Bộ sưu tập : .emptyEnumutions (), .emptyIterator (), .emptyListIterator ()
  • Tự động xóa
  • Có thể ném: .addSuppressed (), .getSuppressed () và hàm tạo 4 đối số
  • Nhân vật : .compare (), .isSurrogate (), .getName (), .highSurrogate (), .lowSurrogate (), .isBmpCodePoint () (nhưng mà không .isAlphabetic () và .isIdeographic ())
  • Hệ thống: .lineSpayator () (không có giấy tờ?)
  • java.lang.reflect.Modifier :. classModifier (), .constructorModifier (), .fieldModifier (), .interfaceModifier (), .methodModifier ()
  • Networkinterface : .getIndex (), .getByIndex ()
  • InetSocketAddress : .gethostString ()
  • InetAddress : .getLoopbackAddress ()
  • Bộ ghi : .getGlobal ()
  • Đồng thờiLinkedDeque
  • AbstractQueuedSyn Syncizer: .hasQueuedPredESEors ()
  • DeflaterOutputStream : 3 hàm tạo với "syncFlush".
  • Deflater : .NO_FLUSH, .SYNC_FLUSH, .ULL_FLUSH, .deflate () với 4 đối số

Về cơ bản là tất cả. Cụ thể, NIO 2.0 không tồn tại và Arrays.asList vẫn không phải là @SafeVarargs.


2
Câu trả lời chính xác. Tôi hy vọng hỗ trợ cấp độ jvm đầy đủ sẽ sớm xảy ra trong tương lai, nio2và những điều tốt đẹp khác chắc chắn sẽ là một tin tốt.
SD

4
Đáng nói là AutoCloseablegiao diện đó không tồn tại trong thời gian chạy Android cho đến khi có ICS (hoặc có lẽ cho đến HoneyComb). Vì vậy, ngay cả khi bạn sử dụng android.jar đã vá, bạn sẽ nhận được NoClassDefFoundErrortrên hệ thống 2.x.
Thần tượng

2
@deviant: Điều đó đòi hỏi phải sửa đổi máy ảo Dalvik, vì sử dụng lambda Java 8 invokedynamickhông được hỗ trợ bởi JVM nhắm mục tiêu Java 6.
kennytm

2
Bạn có thể muốn thêm một bản cập nhật kể từ Android studio 3.2, Ngôn ngữ cấp 7 được hỗ trợ đầy đủ, cũng như dùng thử với các tài nguyên nếu bạn đang biên dịch với KitKat
JRaymond

4
thử với các tài nguyên hiện có thể được sử dụng trên SDK 19 (Android Kitkat). xem công cụ.android.com/recent/androidstudio032release
Mohamed El-Nakib

70

EDIT: Tại thời điểm này được viết, bản phát hành mới nhất là Android 9 và Eclipse Indigo. Điều đã thay đổi kể từ đó.

  • Câu trả lời thực tế

Vâng, tôi đã thử. Nhưng đây không phải là một thử nghiệm tuyệt vời vì khả năng tương thích bị giới hạn ở cấp 6 mà không có cách nào (ít nhất là cách đơn giản) để thực sự sử dụng java 7:

  • Đầu tiên tôi đã cài đặt JDK7 trên máy chưa cài đặt JDK khác - Eclipse và Android cũng không được cài đặt:

7 là cài đặt duy nhất trên máy này

  • Sau đó, tôi đã cài đặt một Indigo Eclipse hoàn toàn mới và kiểm tra xem nó thực sự đang sử dụng JDK 7 (vì đây là cái duy nhất và vì đây là cái tôi đã chọn nên tôi sẽ rất ngạc nhiên)

7 là chỉ được sử dụng bởi Eclipse này

  • Sau đó, tôi đã cài đặt phiên bản Android SDK mới nhất (EDIT: Honeycomb, API13, tại thời điểm bài viết này được viết). Nó tìm thấy JDK 7 của tôi và được cài đặt đúng cách. Tương tự đối với ADT.

  • Nhưng tôi đã có một bất ngờ khi cố gắng biên dịch và chạy ứng dụng Hello Word Android. Khả năng tương thích được đặt thành Java 6 mà không có cách nào buộc nó thành Java 7:

Khả năng tương thích bị giới hạn ở Java 6

  • Tôi đã thử với một dự án không phải Android, một dự án Java thông thường và tôi đã có lời giải thích. Mức độ tương thích dường như bị giới hạn bởi Eclipse (xem thông báo ở dưới cùng của hình ảnh sau):

Eclipse tự giới hạn mức độ tương thích cấp 6

Vì vậy, tôi đã Hello World làm việc, và cũng có các ứng dụng khác, phức tạp hơn và sử dụng SQLite, Listview, SensorCamera, nhưng điều này chỉ chứng minh rằng khả năng tương thích xử lý của Java 7 dường như được thực hiện tốt và làm việc với Android.

Vì vậy, có ai đó đã thử với Ant cũ tốt, để vượt qua giới hạn Eclipse đã thấy ở trên không?

  • Câu trả lời

Dù sao, SDK được thiết kế để được sử dụng với Java 5 hoặc 6, như được giải thích ở đây .

Chúng tôi có thể có một cái gì đó hoạt động với Java 7, nhưng nó sẽ hoạt động "tình cờ". Tòa nhà của DEX có thể hoạt động chính xác hoặc không, và một khi DEX được xây dựng, nó có thể hoạt động hoặc không. Điều này bởi vì sử dụng một JDK không đủ điều kiện cho kết quả không thể đoán trước theo định nghĩa.

Ngay cả khi ai đó đã thành công xây dựng một ứng dụng Android theo Java 7 đơn giản, điều này không đủ điều kiện cho JDK. Quá trình tương tự được áp dụng cho một ứng dụng khác có thể thất bại hoặc ứng dụng kết quả có thể có lỗi liên quan đến việc sử dụng JDK đó. Không được khuyến khích.

Đối với những người tham gia phát triển ứng dụng web, điều này giống hệt như việc triển khai một ứng dụng web được xây dựng theo Java 5 hoặc 6 trong một máy chủ ứng dụng chỉ đủ điều kiện cho Java 4 (ví dụ: Weblogic 8). Điều này có thể hoạt động, nhưng đây không phải là thứ có thể được khuyến nghị cho các mục đích khác ngoài việc thử.


1
Cảm ơn đã xem xét chi tiết. Vì vậy, có vẻ như bạn không thể sử dụng các tính năng ngôn ngữ Java 7 nhưng vẫn sử dụng Java 7 như Java 6. Hy vọng điều này sẽ sớm thay đổi :)
Daniel Ryan

Đây là với Eclipse. Với Ant, điều này có lẽ là có thể. Tôi hy vọng ai đó sẽ làm bài kiểm tra và tôi tự trách mình vì quá lười biếng để làm điều đó :)
Shlublu

Có Varga, nhưng tôi không nghĩ giới hạn phiên bản trình biên dịch đến từ Ant mà là từ Eclipse.
Shlublu

2
Cũng lưu ý rằng nếu đồ chơi của bạn có nhiều phiên bản Java thì các công cụ được cung cấp không tương thích. Ý tôi là nếu lần đầu tiên bạn ký ứng dụng của mình với jarsigner từ các công cụ java 6 và sau đó cài đặt java 7 và ký một phiên bản mới của ứng dụng của chúng tôi với jarsigner đi kèm với java 7 và cùng kho khóa như trước đó các chữ ký sẽ không khớp !
Timo

38

Trích dẫn từ dalvikvm.com:

dx, được bao gồm trong SDK Android, chuyển đổi các tệp Lớp Java của các lớp Java được biên dịch bởi trình biên dịch Java thông thường thành định dạng tệp lớp khác (định dạng .dex)

Điều đó có nghĩa là, tệp nguồn .java không quan trọng, nó chỉ là mã byte. Class.

Theo như tôi biết, chỉ inv invocate được thêm vào mã byte JVM trong Java 7, phần còn lại tương thích với Java 6. Bản thân ngôn ngữ Java không sử dụng invokeocate . Các tính năng mới khác, như câu lệnh chuyển đổi sử dụng String s hoặc multi- Catch chỉ là đường tổng hợp và không yêu cầu thay đổi mã byte. Ví dụ, đa bắt chỉ sao chép chặn bắt cho từng ngoại lệ có thể.

Vấn đề duy nhất là các lớp mới được giới thiệu trong Java 7 bị thiếu trong Android, như AutoClosizable , vì vậy tôi không chắc liệu bạn có thể sử dụng tính năng thử tài nguyên (ai đó đã thử không?).

Bất kỳ ý kiến ​​về điều đó? Tui bỏ lỡ điều gì vậy?


2
Bây giờ vấn đề là làm thế nào để chúng ta cấu hình sao cho mã nguồn Java 7 biên dịch thành các tệp lớp Java 6, đặc biệt là trong nhật thực?
Randy Sugianto 'Yuku'

Câu hỏi duy nhất còn lại là tại sao bạn thậm chí sẽ bận tâm?
Warpzit

@Warpzit câu hỏi lớn hơn nên là Tại sao một nhà phát triển sẽ không bận tâm cho tất cả sự nhầm lẫn này?
Amit

@ Nhận bởi vì anh ấy nhận ra Android khác với Java và để làm việc với Android, anh ấy phải sử dụng các công cụ được cung cấp.
Warpzit

2
@Warpzit Câu hỏi duy nhất của anh là " Android có thể hiểu java 7 không? " Sự thiếu hiểu biết không bao giờ là một giải pháp / câu trả lời ...
Amit

12

Kể từ Android SDK v15, cùng với Eclipse 3.7.1, Java 7 không được hỗ trợ để phát triển Android. Đặt khả năng tương thích nguồn thành 1.7 bắt buộc cài đặt khả năng tương thích tệp. Class được tạo thành 1.7, dẫn đến lỗi sau bởi trình biên dịch Android:

Android yêu cầu trình biên dịch tuân thủ cấp 5.0 hoặc 6.0. Tìm thấy '1.7' thay vào đó. Vui lòng sử dụng Công cụ Android> Sửa thuộc tính dự án.


5

Để mở rộng câu trả lời trên của @KennyTM, nếu bạn đang nhắm mục tiêu 4.0.3 trở lên ( minSdkVersion = 15 ), bạn có thể sử dụng các API ẩn bằng cách thêm một vài lớp vào SDK android.jar của mục tiêu.

Khi bạn thực hiện việc này, bạn có thể sử dụng tài nguyên thử với bất kỳ Đóng, cũng như triển khai AutoClosizable trong các lớp của riêng bạn.

Tôi đã tạo một zip chứa các nguồn và nhị phân của tất cả các lớp cần sửa đổi trong android.jar để cung cấp các API này. Bạn chỉ cần giải nén nó và thêm các nhị phân vào
android-sdk / platform / android-NN / android.jar của bạn

Bạn có thể tải xuống từ đây: http://db.tt/kLxAYWbr

Cũng đáng chú ý là, trong vài tháng qua, Elliott Hughes đã thực hiện một vài cam kết để cây Android: kết thúc AutoCloseable , thêm SafeVarargs , API khác nhau unhidden , cố định constructor bảo vệ Throwable củahỗ trợ bổ sung cho phiên bản 51 tập tin lớp học trong dx . Vì vậy, cuối cùng cũng có một số tiến bộ đang diễn ra.

Chỉnh sửa (tháng 4 năm 2014):

Với việc phát hành SDK 19, không còn cần thiết phải vá android.jar bằng các API bổ sung.

Phương pháp tốt nhất để sử dụng tài nguyên dùng thử trong Android Studio cho một ứng dụng nhắm mục tiêu 4.0.3 trở lên ( minSdkVersion = 15 ) là thêm các mục sau compileOptionsvào 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 Studio sẽ phàn nàn rằng không thể sử dụng tài nguyên thử với cấp API này, nhưng kinh nghiệm của tôi là nó có thể. Dự án sẽ xây dựng và chạy mà không gặp sự cố trên các thiết bị có 4.0.3 trở lên. Tôi đã trải nghiệm không có vấn đề với điều này, với một ứng dụng đã được cài đặt vào thiết bị 500k +.

Lỗi Android Studio

Để bỏ qua cảnh báo này, hãy thêm những điều sau vào lint.xml:

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

1
Tôi thấy thú vị khi cảnh báo mã Android Studio nói rằng tài nguyên dùng thử là mới trong API 13 và tôi nên sử dụng nó. Mặc dù không có thời gian để thực sự kiểm tra nếu nó hoạt động chính xác.
Daniel Ryan

1

Có vẻ như làm cho điều này hoạt động với kiến ​​thuần là một chút bùn.

Nhưng nó đã làm việc cho tôi: http://www.informit.com/articles/article.aspx?p=1966024


1
Tôi đã tìm kiếm điều này trong một thời gian dài. Để giảm bớt rắc rối cho mọi người thông qua việc lọc qua bài viết, bạn sẽ cần thay đổi dòng `<property name =" java.source "value =" 1.5 "/>` trong build.xml do android cung cấp (không phải là trong dự án của bạn!). Đối với tôi, đó là trong /opt/android-sdk-update-manager/tools/ant/build.xml
Mateusz

Không, bạn không có. Bạn có thể ghi đè lên các thuộc tính đó bằng custom_rules.xml, xem câu trả lời của tôi ở đây: stackoverflow.com/a/24608415/194894
Flow

1

Để sử dụng các tính năng Java 7 trong xây dựng mã bởi hệ thống xây dựng dựa trên kiến ​​của Android, chỉ cần đặt các mục sau trong custom_rules.xmlthư mục gốc dự án của bạn:

custom_rules.xml:

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

0

Một số người có thể quan tâm đến dự án git này mà tôi đã tìm thấy, dường như cho phép chạy Java 7 trên Android. https://github.com/yareally/Java7-on-Android

Tuy nhiên, có quá nhiều rủi ro nếu tôi thêm điều này vào dự án hiện tại mà tôi làm việc. Vì vậy, tôi sẽ đợi cho đến khi Google chính thức hỗ trợ Java 7.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.