Java의 속성, 메소드 및 클래스를 선언 할 때 키워드 결승을 사용하여 수정할 수 있습니다. 최종 변수는 상수이며 한 번만 할당 할 수 있습니다. 최종 방법은 서브 클래스로 다시 작성할 수 없습니다. 최종 클래스는 상속받을 수 없습니다.
1. 최종 회원
최종 필드를 선언하면 최적화가 최적화 결정을 더 잘 수행하는 데 도움이됩니다. 컴파일러가 필드의 값이 변경되지 않는다는 것을 알고 있으므로 레지스터의 값을 안전하게 캐시 할 수 있기 때문입니다. 최종 필드는 또한 컴파일러가 필드를 읽기 전용하도록함으로써 추가 수준의 보안을 제공합니다.
1.1 최종 회원 과제에 대해
1) Java에서는 일반 변수를 기본적으로 초기화 할 수 있습니다. 그러나 최종 유형의 변수는 명시 적으로 초기화되어야합니다.
2) 최종 회원은 한 번만 초기화 할 수 있으며 초기화 될 수 있습니다.
3) 최종 멤버는 선언시 (최종 변수가 정의 될 때 최종 변수에 직접 값을 할당) 또는 생성자에 초기화해야하며 다른 곳에서는 초기화 할 수 없습니다.
예 1 Bat.java
공개 클래스 BAT {Final Double Pi = 3.14; // 정의 된 경우 최종 INT I를 할당합니다. // 생성자에서 초기화되기 때문에 최종 목록 <BAT> 목록은 여기에 할당 할 수 없습니다. // 생성자에서 초기화되어야하기 때문에 여기에서 bat ()를 할당 할 수 없습니다 {i = 100; List = New LinkedList <Bat> (); } bat (int ii, list <bat> l) {i = ii; 목록 = l; } public static void main (String [] args) {bat b = new Bat (); b.list.add (new bat ()); // bi = 25; // B.list = new ArrayList <Bat> (); System.out.println ( "i =" + bi + "목록 유형 :" + b.list.getClass ()); b = 새 박쥐 (23, New ArrayList <BAT> ()); b.list.add (new bat ()); System.out.println ( "i =" + bi + "목록 유형 :" + b.list.getClass ()); }}
결과:
i = 100 목록 유형 : 클래스 java.util.linkedListi = 23 목록 유형 : 클래스 java.util.arraylist
주 방법에는 주석을달라고 진술 한 줄이 있습니다. 주석을 제거하면 프로그램이 컴파일 할 수 없습니다. 이것은 그것이 I의 값인지 또는 목록의 유형이든, 일단 초기화되면 변경할 수 없음을 의미합니다. 그러나 B는 다시 이리셔티브 화함으로써 i 또는 목록 유형을 지정할 수 있습니다.
1.2 최종 참조 필드의 잘못된 초기화
최종 필드를 올바르게 사용하는 것은 약간 번거롭습니다. 특히 생성자가 예외를 던질 수있는 객체 참조의 경우. 최종 필드는 각 생성자에서 한 번만 초기화되어야하므로 최종 오브젝트로 참조 된 생성자가 예외를 던질 수있는 경우 컴파일러는 필드가 초기화되지 않았다는 오류를보고 할 수 있습니다. 컴파일러는 일반적으로 두 개의 Mutex 코드 브랜치의 각 분기 (예 : ... 다른 블록)의 초기화가 한 번만 발생하지만 일반적으로 "용서하는"것은 아닙니다.
다음 코드에는 일반적으로 문제가 있습니다.
Class Thingie {public static thingie getDefaultThingie () {return new thingie (); }} public class foo {private final thingie thingie; public foo () {try {thingie = new Thingie (); } catch (예외 e) {thingie = thingie.getDefaultThingie (); // 오류 : 최종 필드 thatie가 이미 할당되었을 수 있습니다}}}}
이것을 수정할 수 있습니다.
공개 클래스 Foo {개인 최종 Thingie Thingie; public foo () {Thingie tempthingie; try {tempthingie = new Thingie (); } catch (예외 e) {tempthingie = thingie.getDefaultThingie (); } thingie = tempthingie; }}
1.3 최종 회원 사용에 대해
클래스에서 변수를 정의하면 최종 키워드를 추가하면이 변수가 초기화되면 변경할 수 없습니다. 여기서 불변성의 의미는 기본 유형에 대해 그 값이 불변이 아니며 객체 변수에 대해 더 이상 참조를 변경할 수 없다는 것입니다. 그러나 물체 자체를 수정할 수 있으며 Java는 객체를 일정하게 만드는 방법을 제공하지 않습니다. 이 제한은 객체 인 배열에도 적합합니다.
예 2
Private Final Int Val_one = 9; 개인 정적 최종 INT Val_TWO = 99; 공개 정적 최종 INT Val_three = 999;
Val_one과 Val_tow는 컴파일 타임 값을 갖는 최종 원시 유형이므로 둘 다 컴파일 타임 상수로 사용될 수 있으며 유의 한 차이는 없습니다. VAL_THREE는 상수를 정의하는보다 일반적인 방법입니다. 공개로 정의하면 패키지 외부에서 사용할 수 있습니다. 하나의 사본 만 강조하기 위해 정적으로 정의됩니다. 상수임을 나타 내기 위해 최종으로 정의됩니다.
마킹 된 최종 변수는 상수가되지만이 "상수"는이 클래스 내에서만 사용될 수 있으며 클래스 밖에서 직접 사용할 수 없습니다. 그러나 공개 정적 결승을 사용하여 상수를 표시하면이 상수는 글로벌 상수가됩니다 (정적 및 최종의 필드는 변경할 수없는 저장 공간을 차지합니다). 또한, 이러한 방식으로 정의 된 상수는 정의 할 때만 할당 할 수 있으며 다른 곳에서는 사용할 수 없습니다.
예 3
클래스 값 {int i; 공공 가치 (int i) {this.i = i; }} public class finalData {private static random rand = new random (); 개인 문자열 ID; Public FinalData (String ID) {this.id = id; } private final int i4 = rand.nextint (20); 정적 최종 int i5 = rand.nextint (20); public String toString () {return id + ":" + "i4 :" + i4 + ", i5 =" + i5; } public static void main (String [] args) {FinalData fd1 = new FinalData ( "FD1"); System.out.println (fd1); System.out.println ( "새로운 FinalData 생성"); FinalData FD2 = 새로운 FinalData ( "FD2"); System.out.println (fd1); System.out.println (FD2); }}
결과
FD1 : i4 : 6, i5 = 3 새로운 FinalDatafd1 : i4 : 6, i5 = 3fd2 : i4 : 17, i5 = 3
예제 섹션은 최종 값을 정적 (i5) 및 비 정적 (i4)으로 정의하는 것의 차이를 보여줍니다. 이 차이는 컴파일러가 컴파일 된 값을 동일하게 처리하기 때문에 런타임 중에 값이 초기화 될 때만 나타납니다. (그리고 최적화에서 사라질 수 있습니다.) 프로그램을 실행할 때이 차이점을 볼 수 있습니다. FD1 및 FD2에서 두 번째 FinalData 객체를 작성하여 i5의 값을 변경할 수 없습니다. 이것은 정적이기 때문에 새 개체가 생성 될 때마다 로딩시 초기화되기 때문입니다.
예 4
클래스 값 {int i; 공공 가치 (int i) {this.i = i; }} 공개 클래스… {개인 값 v1 = 새 값 (11); 개인 최종 값 v2 = 새 값 (22); 개인 정적 최종 값 v3 = 새 값 (33); …} public static void main (string [] args) {… fd1.v2.i ++; // ok- 오브젝트는 일정하지 않습니다! fd1.v1 = 새 값 (9); // OK- 최종 FD1.V2 = 새로운 값 (0); // 오류 : 참조를 변경할 수 없습니다. 참조 FD1.V3 = 새 값 (1); 오류 : 참조를 변경할 수 없습니다…} V1에서 V3까지 변수는 최종 참조의 의미를 보여줍니다. main ()에서 볼 수 있듯이 v2가 최종적이기 때문에 그 값을 변경할 수 없다고 생각할 수 없습니다. 참조이므로 최종은 V2를 다른 새 개체에 다시 가리킬 수 없다는 것을 의미합니다.
예 5
공개 클래스… {private final int [] a = {1,2,3,4,5,6}; …} public static void main (string [] args) {… fd1.a = new int [3]; // 오류 : 참조를 변경할 수 없습니다…} 배열에 대해 동일한 의미를 갖는 (값을 변경할 수 있지만 새 개체를 가리킬 수는 없음) 배열은 또 다른 참조입니다.
1.4 최종 배열의 한계를 해결하십시오
배열 참조는 최종적으로 선언 될 수 있지만 배열의 요소는 할 수 없습니다. 이는 공개 최종 배열 필드를 노출 시키거나 해당 필드에 대한 참조를 해당 필드에 반환하는 클래스가 변경 가능하지 않음을 의미합니다.
// 불변하지 않음 - 상태 배열은 악성으로 수정 될 수 있습니다. // callerpublicclass dangerousstates {private final string [] states = new String [] { "alabama", "알래스카", "ect"}; public String [] getstates () {return states; }}
마찬가지로, 객체 참조는 최종 필드로 선언 될 수 있지만, 참조하는 객체는 여전히 변동성이있을 수 있습니다. 최종 필드를 사용하여 변하지 않는 객체를 만들려면 배열 또는 변이 가능한 객체가 클래스를 "탈출"하는 것에 대한 참조를 방지해야합니다. 배열을 반복적으로 복제하지 않고도이 작업을 수행하려면 쉽게 배열을 목록으로 변환하는 것입니다.
// 불변 - 대신에 변하지 않는 목록을 반환합니다. 개인 최종 목록 stateAslist = new acpractList () {public object get (int n) {return states [n]; } public int size () {return states.length; }}; 공개 목록 GetStates () {return StateAsList; }}
최종 매개 변수 사용에 대해 1.5
또 다른 사용법은 메소드의 매개 변수를 최종으로 정의하는 것입니다. 기본 유형의 변수의 경우 기본 유형의 변수는 메소드를 호출 할 때 값을 전달하기 때문에 실질적인 의미가 없습니다. 그러나 객체 변수의 경우 객체 변수가 통과 할 때 참조가 전달되기 때문에 매우 실용적입니다. 이러한 방식으로, 메소드에서 객체 변수를 수정하면 호출 문의 객체 변수에도 영향을 미칩니다. 메소드의 객체 변수를 메소드의 매개 변수로 변경할 필요가 없으면 선언에 최종 최종을 사용하면 의도하지 않게 수정 및 호출 방법에 영향을 미치지 않습니다.
1.6 내부 클래스의 매개 변수 변수에 대해
또한 내부 클래스의 메소드에서 매개 변수 변수를 사용할 때이 매개 변수는 사용하기 전에 최종적으로 선언해야합니다.
예제 6 Inclass.java
공개 클래스 포함 {void Innerclass (Final String Str) {class iclass {iclass () {system.out.println (str); }} iclass ic = new iclass (); } public static void main (string [] args) {conflass inc = new conflass (); inc.innerclass ( "Hello"); }} 2. 최종 방법
2.1 최종 방법 사용
1) 상속 프로세스 동안 특정 함수의 동작이 변경되지 않도록하기 위해 최종 방법을 사용할 수 있습니다.
2) 클래스의 모든 개인 및 정적 방법은 자연스럽게 최종입니다.
2.2 최종 및 개인 키워드
클래스의 모든 개인 방법은 암시 적으로 최종적으로 지정됩니다. 개인 방법을 사용할 수 없으므로 덮어 쓰는 것은 아닙니다.
"오버라이드"는 메소드가 기본 클래스의 인터페이스의 일부인 경우에만 나타납니다. 즉, 객체를 원시 유형으로 위쪽으로 변환하고 동일한 방법을 호출 할 수 있어야합니다. 메소드가 비공개 인 경우 기본 클래스의 인터페이스의 일부가 아닙니다. 클래스에 숨겨져있는 코드 일 뿐이지 만 같은 이름이 있습니다. 그러나 공개, 보호 또는 패키지 액세스 방법이 내보내기 클래스에서 동일한 방식으로 생성되는 경우,이 방법은 기본 클래스에서 발생하는 "동일한 이름으로 만"을 생성하지 않습니다. 이 시점 에서이 방법을 무시하지 않고 새로운 메소드를 생성했습니다. 개인 방법을 만질 수없고 효과적으로 숨길 수 있기 때문에, 그에 속하는 클래스의 조직 구조의 존재를 제외하고는 아무것도 고려할 필요가 없습니다.
3. 최종 수업
클래스가 최종으로 정의되면 클래스를 상속받을 수 없습니다. 그리고 최종 클래스는 상속을 금지하기 때문에 최종 클래스의 모든 방법은 덮어 쓰지 않기 때문에 암시 적으로 최종적으로 지정됩니다.
최종은 클래스 나 방법에 사용됩니다. 예를 들어, 클래스 X 메소드의 구현이 메소드 m이 어떤 식 으로든 작동한다고 가정한다고 가정합니다. X 또는 M을 최종으로 선언하면 파생 클래스가 이러한 방식으로 M을 재정의하는 것을 방지하여 X가 비정상적으로 작동합니다. 이러한 내부 상관 관계없이 X를 구현하는 것이 더 나을 수도 있지만, 항상 가능하지는 않으며 최종을 사용하면 미래의 양립 할 수없는 변화를 방지 할 수 있습니다.
추신 : Final의 차이점, 마지막으로 마무리됩니다