Android의 Java 7 언어 기능


188

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


10
또는 Java 7 언어 기능을 사용할 수 있지만 Java 6 바이트 코드로 컴파일 할 수 있습니까?
MatrixFrog

2
이제 Android Studio에서 새 프로젝트를 생성 할 때 "minSdkVersion이 19보다 작 으면 리소스를 사용할 수는 없지만 다른 Java 7 언어 기능은 괜찮습니다"라는
알림을 표시

1
그래, 나도 알아 :) 우리는 마침내 프로젝트에서 Java 7을 사용하고 있습니다.
Daniel Ryan

답변:


165

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가 아닙니다.


2
좋은 대답입니다. 조만간 완전한 jvm 수준의 지원이 이루어지기를 희망 nio2하며 다른 좋은 점은 분명히 좋은 소식이 될 것입니다.
SD

4
AutoCloseableICS (또는 HoneyComb)까지는 Android 런타임에 인터페이스가 존재하지 않는다는 점을 언급 할 가치가 있습니다. 따라서 패치 된 android.jar을 사용하더라도 NoClassDefFoundError2.x 시스템에서 받게 됩니다.
Idolon

2
@deviant : Java 6 람다가 invokedynamicJava 6을 대상으로하는 JVM에서 지원하지 않기 때문에 Dalvik VM을 수정해야합니다 .
kennytm

2
KitKat
JRaymond

4
이제 SDK 19 (Android Kitkat)에서 리소스를 사용해보십시오. tools.android.com/recent/androidstudio032released
Mohamed El-Nakib

70

편집 : 이것이 작성된 시점에서 최신 릴리스는 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)로 배포하는 것과 동일합니다. 이것은 효과가있을 수 있지만 시도하는 것 이외의 다른 목적으로 권장 할 수있는 것은 아닙니다.


1
자세한 검토에 감사드립니다. 따라서 Java 7 언어 기능을 사용할 수 없지만 Java 7을 Java 6으로 계속 사용할 수 있습니다. 곧 변경 될 것입니다 :)
Daniel Ryan

이것은 Eclipse와 관련이 있습니다. Ant를 사용하면 가능할 것입니다. 나는 누군가가 시험을하기를 희망하며 그것을하기에는 너무 게으른 것에 대해 스스로를 비난한다 :)
Shlublu

예 Varga,하지만 컴파일러 버전 제한은 Ant가 아니라 Eclipse에서 온 것으로 생각합니다.
Shlublu

2
또한 여러 버전의 Java를 사용하는 경우 제공된 도구가 호환되지 않습니다. 내 말은 Java 6 도구에서 jarsigner로 앱에 먼저 서명 한 다음 나중에 java 7을 설치하고 이전에 java 7 및 동일한 키 저장소와 함께 제공된 jarsigner로 새 버전의 앱에 서명하면 서명이 일치하지 않는다는 것입니다 !
Timo

38

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 기능을 사용할 수 있는지 확실하지 않습니다 (누군가 시도 했습니까?).

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


2
이제 문제는 Java 7 소스 코드가 특히 Eclipse에서 Java 6 클래스 파일로 컴파일되도록 구성하는 방법입니다.
랜디 Sugianto '유쿠

남은 유일한 질문은 왜 귀찮게하겠습니까?
Warpzit

@Warpzit 더 큰 문제는 왜 개발자가이 모든 혼란을 귀찮게하지 않습니까?
Amit

@Amit은 Android가 Java와 다르다는 사실을 깨닫게되었으므로 Android와 작업하려면 제공된 도구를 사용해야합니다.
Warpzit

2
@Warpzit 그의 유일한 질문은 " Android가 Java 7을 이해할 수 있습니까? "입니다. 무지는 결코 해결책 / 답변이 아닙니다.
Amit

12

Eclipse 3.7.1과 함께 Android SDK v15부터 Java 7은 Android 개발에 지원 되지 않습니다 . 소스 호환성을 1.7로 설정하면 생성 된 .class 파일 호환성을 1.7로 설정해야하며, 이로 인해 Android 컴파일러에서 다음 오류가 발생합니다.

Android에는 컴파일러 준수 레벨 5.0 또는 6.0이 필요합니다. 대신 '1.7'을 찾았습니다. Android 도구> 프로젝트 속성 수정을 사용하십시오.


5

@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>

1
Android Studio 코드 경고에 try-with-resources가 API 13의 새로운 기능이므로 사용하고 있어야한다는 점이 흥미 롭습니다. 실제로 제대로 작동하는지 테스트 할 시간이 없지만.
Daniel Ryan

1

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

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


1
나는 이것을 오랫동안 찾았다. 기사를 통한 필터링으로 사람들의 문제를 줄이려면 android에서 제공하는 build.xml에서`<property name = "java.source"value = "1.5"/> 줄을 변경해야합니다. 프로젝트!). 나를 위해 그것은 /opt/android-sdk-update-manager/tools/ant/build.xml에있었습니다
Mateusz Kowalczyk

아뇨. 이 속성을 덮어 쓸 수 있습니다. custom_rules.xml여기에서 내 대답을 참조하십시오 : stackoverflow.com/a/24608415/194894
Flow

1

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>

0

어떤 사람들은 내가 찾은이 자식 프로젝트에 관심이있을 수 있습니다. 안드로이드에서 Java 7을 실행할 수있는 것 같습니다. https://github.com/yareally/Java7-on-Android

그러나 현재 작업중 인 프로젝트에 이것을 추가하면 너무 위험합니다. Google이 공식적으로 Java 7을 지원할 때까지 기다립니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.