[java] Android의 Java 7 언어 기능

누군가 Android에서 새로운 Java 7 언어 기능을 사용해 보았는지 궁금하십니까? 안드로이드가 자바가 내뿜는 바이트 코드를 읽고 그것을 dex로 바꾼다는 것을 알고 있습니다. 그래서 내 질문은 Java 7의 바이트 코드를 이해할 수 있습니까?



답변

Android Studio를 사용하는 경우 패치없이 Java 7 언어 가 자동으로 활성화되어야합니다. Try-with-resource에는 API 레벨 19 이상이 필요하며 NIO 2.0 항목이 없습니다.

Java 7 기능을 사용할 수 없으면 을 편집하는 방법에 대한 @Nuno 의 답변을 참조 하십시오 build.gradle.

다음은 역사적 관심사를위한 것입니다.


Java 7의 작은 부분은 확실히 Android와 함께 사용할 수 있습니다 (참고 : 4.1에서만 테스트했습니다).

우선, Java 컴파일러 1.5 및 1.6 만 호환되도록 하드 코딩 되어 있기 때문에 Eclipse의 ADT를 사용할 수 없습니다 . ADT를 다시 컴파일 할 수는 있지만 전체 Android를 함께 다시 컴파일하는 것 외에는 간단한 방법이 없습니다.

그러나 Eclipse를 사용할 필요는 없습니다. 예를 들어 Android Studio 0.3.2 , IntelliJ IDEA CE 및 기타 javac 기반 IDE는 Android 로의 컴파일을 지원 하며 다음을 사용하여 최대 Java 8까지 준수를 설정할 수 있습니다.

  • 파일 → 프로젝트 구조 → 모듈 → (두 번째 창에서 모듈 선택) → 언어 수준 → ( “7.0-다이아몬드, ARM, 멀티 캐치 등”선택)

IntelliJ에서 Java 7 사용

기능 은 Java 7 언어 기능 만 허용 하며 , 절반의 향상도 라이브러리에서 제공되므로 어떠한 이점도 얻을 수 없습니다. 사용할 수있는 기능은 라이브러리에 의존하지 않는 기능입니다.

  • 다이아몬드 연산자 ( <>)
  • 스트링 스위치
  • 다중 캐치 ( catch (Exc1 | Exc2 e))
  • 숫자 리터럴의 밑줄 ( 1_234_567)
  • 이진 리터럴 ( 0b1110111)

그리고이 기능들은 아직 사용할 수 없습니다 :

  • try가진 – – 자원 문 -가 존재하지 않는 인터페이스 “java.lang.AutoCloseable”를 필요로하기 때문에 (이 4.4에서 공개적으로 사용할 수 있습니다)
  • @SafeVarargs 주석- “java.lang.SafeVarargs”가 없기 때문에

… “yet”:) 안드로이드의 라이브러리가 1.6을 대상으로하지만 안드로이드 소스에는 AutoCloseable 과 같은 인터페이스가 포함되어 있으며 Closeable 과 같은 기존 인터페이스 는 AutoCloseable에서 상속됩니다 (SafeVarargs는 실제로 누락되었습니다). 우리는 성찰을 통해 그 존재를 확인할 수있었습니다. Javadoc에 @hide태그가있어 “android.jar”에 포함되지 않기 때문에 단순히 숨겨져 있습니다.

이미 존재하는 문제 등이 내가 숨겨진 내부 API를 사용할 수와 안드로이드 SDK를 구축하려면 어떻게합니까? 그 방법을 다시 얻는 방법에 대해. 당신은 단지 필요 교체 기존의 “android.jar”사용자 정의 하나, 자바 (7) API를 한 후 많은 사람들이 사용할 수있게됩니다 우리와 현재 플랫폼의 참조 (절차가 Eclipse에서 유사하다. 프로젝트 구조 → SDK를 확인하십시오.)

AutoCloseable 외에도 다음과 같은 Java 7 라이브러리 기능 도 공개됩니다.

  • ConcurrentModificationException, LinkageError 및 AssertionError의 예외 체인 생성자
  • 프리미티브의 정적 .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 ()
  • 자동 닫기
  • 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 ()
  • 로거 : .getGlobal ()
  • 동시 링크
  • AbstractQueuedSynchronizer : .hasQueuedPredecessors ()
  • DeflaterOutputStream : “syncFlush”를 가진 3 개의 생성자.
  • 디플렉터 : .NO_FLUSH, .SYNC_FLUSH, .FULL_FLUSH, .deflate () 사 개 인수

그게 전부입니다. 특히 NIO 2.0은 존재하지 않으며 Arrays.asList는 여전히 @SafeVarargs가 아닙니다.


답변

편집 : 이것이 작성된 시점에서 최신 릴리스는 Android 9 및 Eclipse Indigo였습니다. 그때부터 상황이 바뀌 었습니다.

  • 실용 답변

예, 시도했습니다. 그러나 호환성이 실제로 Java 7을 사용하는 방법 (최소한 방법은 아님)으로 레벨 6으로 제한되었으므로 이것은 훌륭한 테스트가 아닙니다.

  • 먼저 다른 JDK가 설치되지 않은 컴퓨터에 JDK7을 설치했습니다. Eclipse 및 Android도 설치되지 않았습니다.

7은이 머신에 설치된 유일한 제품입니다

  • 그런 다음 새로운 Eclipse Indigo를 설치하고 실제로 JDK 7을 사용하고 있는지 확인했습니다.

7은이 이클립스가 사용하는 유일한 제품입니다

  • 그런 다음 최신 버전의 Android SDK를 설치했습니다 (이 게시물 작성 당시 편집 : Honeycomb, API13). JDK 7을 찾아서 올바르게 설치했습니다. ADT도 마찬가지입니다.

  • 그러나 Hello Word Android 앱을 컴파일하고 실행하려고 할 때 놀랐습니다. 호환성은 Java 6으로 강제 설정할 수없는 Java 6으로 설정되었습니다.

호환성은 Java 6으로 제한됩니다

  • 안드로이드가 아닌 프로젝트, 일반적인 Java 프로젝트로 시도했지만 설명이있었습니다. 호환성 수준은 Eclipse에 의해 제한되는 것 같습니다 (다음 이미지 하단의 메시지 참조).

Eclipse는 레벨 6 호환성으로 제한됩니다.

내가 가진 그래서 안녕하세요을 작업하고, 다른 응용 프로그램은 더 복잡하고 사용 SQLite, Listview, SensorCamera, 그러나 이것은 단지 자바 7의 처리 호환성이 잘 안드로이드로 작동하는 것 같군 것을 증명한다.

그래서 누군가 위에 보이는 Eclipse 제한을 우회하기 위해 좋은 오래된 Ant를 사용해 보았습니까?

  • 이론적 인 답변

어쨌든 SDK는 여기 설명 된대로 Java 5 또는 6과 함께 사용하도록 설계되었습니다 .

Java 7에서 작동하는 것이있을 수 있지만 “우연히”작동합니다. DEX 구축이 제대로 작동하지 않을 수 있으며 DEX가 구축되면 작동 할 수도 있습니다. 이는 규정되지 않은 JDK를 사용하면 정의에 의해 예측할 수없는 결과를 제공하기 때문입니다.

누군가 일반 Java 7에서 Android 앱을 성공적으로 구축 했더라도 JDK를 사용할 수 없습니다. 다른 애플리케이션에 적용된 동일한 프로세스가 실패하거나 결과 애플리케이션에 해당 JDK 사용과 관련된 버그가있을 수 있습니다. 권장하지 않습니다.

webapps 개발에 관여하는 사람들에게는 Java 4 또는 Java 6 용으로 작성된 웹 응용 프로그램을 Java 4 전용 응용 프로그램 서버 (예 : Weblogic 8)로 배포하는 것과 동일합니다. 이것은 효과가있을 수 있지만 시도하는 것 이외의 다른 목적으로 권장 할 수있는 것은 아닙니다.


답변

dalvikvm.com에서 인용 :

Android SDK에 포함 된 dx는 일반 Java 컴파일러에서 컴파일 한 Java 클래스의 Java 클래스 파일을 다른 클래스 파일 형식 (.dex 형식)으로 변환합니다.

즉, .java 소스 파일은 중요하지 않으며 .class 바이트 코드 일뿐입니다.

내가 아는 한 invokedynamic 만 Java 7의 JVM 바이트 코드에 추가되었으며 나머지는 Java 6과 호환됩니다. Java 언어 자체는 invokedynamic을 사용하지 않습니다 . String을 사용 하는 switch 문 또는 멀티 캐치 와 같은 다른 새로운 기능 은 단지 신택 틱 설탕이며 바이트 코드 변경이 필요하지 않습니다. 예를 들어, 멀티 캐치 는 각 가능한 예외에 대한 캐치 블록을 복사합니다 .

유일한 문제는 Java 7에 도입 된 새로운 클래스가 AutoCloseable 과 같은 Android에서 누락 되었기 때문에 try -with-resources 기능을 사용할 수 있는지 확실하지 않습니다 (누군가 시도 했습니까?).

그것에 대한 의견이 있으십니까? 뭔가 빠졌습니까?


답변

Eclipse 3.7.1과 함께 Android SDK v15부터 Java 7은 Android 개발에 지원 되지 않습니다 . 소스 호환성을 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을 구현할 수 있습니다.

이 API를 사용 가능하게하기 위해 android.jar에서 수정해야하는 모든 클래스의 소스 및 바이너리가 포함 된 Zip을 만들었습니다. 압축을 풀고 바이너리를
android-sdk / platforms / android-NN / android.jar에 추가하면됩니다 .

여기에서 다운로드 할 수 있습니다 : http://db.tt/kLxAYWbr

또한 노트의 인 달의 지난 몇 년, 엘리엇 휴즈는 안드로이드 나무에 몇 커밋을했다 : AutoCloseable 마무리 , 추가 SafeVarargs , 숨김 다양한 API , 고정의 Throwable의 보호 생성자DX의 버전 (51) 클래스 파일에 대한 추가 지원 . 그래서 마침내 몇 가지 진전이 있습니다.

편집 (2014 년 4 월) :

SDK 19 릴리스에서는 더 이상 추가 API로 android.jar를 패치 할 필요가 없습니다.

4.0.3 이상 ( minSdkVersion = 15 ) 을 대상으로하는 앱에 대해 Android Studio에서 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 Studio는이 API 수준에서 리소스를 사용하여 리소스를 사용할 수 없다고 불평하지만 내 경험에 따르면 가능합니다. 이 프로젝트는 4.0.3 이상의 장치에서 문제없이 빌드되고 실행됩니다. 500k + 기기에 설치된 앱과 관련하여 아무런 문제가 없었습니다.

안드로이드 스튜디오 오류

이 경고를 무시하려면 다음을 추가하십시오 lint.xml.

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


답변

이것이 순수한 개미와 함께 작동하게하는 것은 약간의 문제입니다.

그러나 그것은 나를 위해 일했다 : http://www.informit.com/articles/article.aspx?p=1966024


답변

Android 개미 기반 빌드 시스템의 코드 빌드에서 Java 7 기능을 사용하려면 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>