자바 의 기초 개념 사용 에 대한 상세 한 설명

20096 단어
클래스 의 초기 화 순 서 는 자바 에 있 습 니 다. 클래스 에는 정적 변수, 정적 초기 화 블록, 구성원 변수, 초기 화 블록, 구조 함수 가 포 함 될 수 있 습 니 다.클래스 간 에 계승 관계 가 존재 할 수 있 습 니 다. 그러면 우리 가 대상 을 예화 할 때 상기 각 부분의 로드 순 서 는 어떻게 됩 니까?
우선 코드 보기:
 
  
class Parent
 {
     public static StaticVarible staticVarible= new StaticVarible("父类-静态变量1");   
     public StaticVarible instVarible= new StaticVarible("父类-成员变量1");

     static
     {
         System.out.println("父类-静态块");
     }

     {
         System.out.println("父类-初始化块");
     }

     public static StaticVarible staticVarible2= new StaticVarible("父类-静态变量2");   
     public StaticVarible instVarible2= new StaticVarible("父类-成员变量2");

     public Parent()
     {
         System.out.println("父类-实例构造函数");
     }
 }

 class Child extends Parent
 {
     public static StaticVarible staticVarible= new StaticVarible("子类-静态变量1");   
     public StaticVarible instVarible= new StaticVarible("子类-成员变量1");

     static
     {
         System.out.println("子类-静态块");
     }

     public Child()
     {
         System.out.println("子类-实例构造函数");
     }

     {
         System.out.println("子类-初始化块");
     }

     public static StaticVarible staticVarible2= new StaticVarible("子类-静态变量2");   
     public StaticVarible instVarible2= new StaticVarible("子类-成员变量2");

    
 }

 class StaticVarible
 {
     public StaticVarible(String info)
     {
         System.out.println(info);
     }
 }

그리고 다음 문장 을 실행 합 니 다:
 
  
Child child = new Child();

출력 결 과 는 다음 과 같 습 니 다.
 
  
父类-静态变量1
父类-静态块
父类-静态变量2
子类-静态变量1
子类-静态块
子类-静态变量2
父类-成员变量1
父类-初始化块
父类-成员变量2
父类-实例构造函数
子类-成员变量1
子类-初始化块
子类-成员变量2
子类-实例构造函数

  
결론.
상기 결 과 를 통 해 알 수 있 듯 이 한 대상 을 예화 할 때 각 부분의 로드 순 서 는 다음 과 같다.
부모 클래스 정적 구성원/부모 클래스 정적 초기 화 블록 -> 하위 클래스 정적 구성원/하위 클래스 초기 화 블록 -> 부모 클래스 구성원 변수/부모 클래스 초기 화 블록 -> 부모 클래스 구조 함수 -> 하위 클래스 구성원 변수/하위 클래스 초기 화 블록 -> 하위 클래스 구조 함수
String 과 관련 된 일 들 이 있 습 니 다. 우선 자바 의 더미 와 스 택 에 대해 이야기 해 보 겠 습 니 다.
• 스 택: 기본 형식 을 저장 합 니 다. char/by te/short/int/long/float/double/boolean • 더미: 인용 형식 을 저장 하 는 동시에 스 택 에 가리 키 는 지침 을 보관 합 니 다. 쓰레기 수 거 는 대상 이 회수 할 수 있 는 지 여 부 를 판단 합 니 다. 스 택 에 포인터 가 있 는 지 여 부 를 판단 하 는 것 입 니 다.String 은 특수 한 데이터 형식 으로서 기본 유형 과 완전히 같 지 않 고 모든 인용 유형 도 아니 며 많은 면접 문제 가 그 모습 을 가지 고 있다.
String 형식 변수의 저장 구조 String 의 저장 구 조 는 두 부분 으로 나 뉘 는데 우 리 는 String a = "abc"로 나 뉜 다.예 를 들 어 String 형식의 저장 방식 을 설명 합 니 다.
1) 스 택 에 char 배열 을 만 들 고 값 은 'a', 'b', 'c' 로 나 뉜 다.
2) 더미 에 String 대상 을 만 듭 니 다.
자바 의 문자열 풀 은 공간 과 자원 을 절약 하기 위해 JVM 은 문자열 풀 을 유지 하거나 나타 난 문자열 의 일 부 를 캐 시 합 니 다.
예 를 들 어 다음 코드:
 
  
String v1 = "ab";
String v2 = "ab";

실제로 v1 = = v2 는 JVM 이 v1 성명 후 'ab' 에 캐 시 를 했 기 때문이다.
그러면 JVM 이 문자열 을 캐 시 하 는 근 거 는 무엇 입 니까?우 리 는 아래 의 코드 를 보 았 습 니 다. 매우 재 미 있 습 니 다.
 
  
public class StringTest {
     public static final String constValue = "ab";
     public static final String staticValue;

     static
     {
         staticValue="ab";
     }

     public static void main(String[] args)
     {
         String v1 = "ab";
         String v2 = "ab";
         System.out.println("v1 == v2 : " + (v1 == v2));
         String v3 = new String("ab");
         System.out.println("v1 == v3 : " + (v1 == v3));
         String v4 = "abcd";
         String v5 = "ab" + "cd";
         System.out.println("v4 == v5 : " + (v4 == v5));
         String v6 = v1 + "cd";
         System.out.println("v4 == v6 : " + (v4 == v6));
         String v7 = constValue + "cd";
         System.out.println("v4 == v7 : " + (v4 == v7));
         String v8 = staticValue + "cd";
         System.out.println("v4 == v8 : " + (v4 == v8));
         String v9 = v4.intern();
         System.out.println("v4 == v9 :" + (v4 == v9));
         String v10 = new String(new char[]{'a','b','c','d'});
         String v11 = v10.intern();
         System.out.println("v4 == v11 :" + (v4 == v11));
         System.out.println("v10 == v11 :" + (v10 == v11));
     }
 }

출력 결과 에 주의 하 십시오:
 
  
v1 == v2 : true
v1 == v3 : false
v4 == v5 : true
v4 == v6 : false
v4 == v7 : true
v4 == v8 : false
v4 == v9 :true
v4 == v11 :true
v10 == v11 :false

모든 판단 이 트 루 로 돌아 가 는 것 은 아니 라 는 것 을 알 게 될 것 이다. 이것 은 우리 위의 말 과 모순 되 는 것 같다.사실은 그렇지 않다.
결론 1. JVM 은 컴 파일 할 때 확인 할 수 있 는 상수 만 캐 시 할 수 있 고 실행 할 때 상수 가 아 닙 니 다.
상기 코드 중의 constValue 는 컴 파일 시 상수 에 속 하고 staticValue 는 실행 시 상수 에 속한다.
2. new 방식 으로 생 성 된 문자열 은 JVM 캐 시 방식 이 다 릅 니 다.
그래서 상기 코드 에서 v1 은 v3 와 같 지 않다.
String 의 이런 디자인 은 향 원 모드 에 속 합 니까?이 화 제 는 비교적 재 미 있 습 니 다. 대부분 디자인 모델 을 이야기 하 는 글 은 향 원 에 대해 이야기 할 때 보통 String 을 예 로 들 지만 향 원 모델 에 속 합 니까?
문자열 과 향 원 의 관 계 는 다음 과 같은 글 을 참고 할 수 있 습 니 다. C\# 문자열 과 향 원 (Flyweight) 모드 에 깊이 들 어가 문자열 의 반전 출력 을 분석 하 는 경우 문자열 을 문자 배열 로 보고 반전 배열 방식 으로 문자열 을 반전 시 킵 니 다.
현란 한 방법 으로 상속 관계 구조 에서 의 방법 을 호출 하여 계승 을 호출 하 는 것 은 대상 을 대상 으로 하 는 디자인 에서 흔히 볼 수 있 는 방식 으로 '코드 재 활용' 을 효과적으로 실현 할 수 있 으 며, 자 류 는 부모 류 방법 을 재 작성 하 는 자유 도 있 기 때문에 부모 류 방법 을 호출 하 는 것 인지, 하위 방법 을 사용 하 는 것 인지 에 문 제 를 가 져 왔 다.
다음 코드 보기:
 
  
public class PropertyTest {

     public static void main(String[] args)
     {
         ParentDef v1 = new ParentDef();
         ParentDef v2 = new ChildDef();
         ChildDef v3 = new ChildDef();
         System.out.println("=====v1=====");
         System.out.println("staticValue:" + v1.staticValue);
         System.out.println("value:" + v1.value);
         System.out.println("=====v2=====");
         System.out.println("staticValue:" + v2.staticValue);
         System.out.println("value:" + v2.value);
         System.out.println("=====v3=====");
         System.out.println("staticValue:" + v3.staticValue);
         System.out.println("value:" + v3.value);
     }
 }

 class ParentDef
 {
     public static final String staticValue = "父类静态变量";
     public String value = "父类实例变量";
 }

 class ChildDef extends ParentDef
 {
     public static final String staticValue = "子类静态变量";
     public String value = "子类实例变量";
 }

출력 결 과 는 다음 과 같 습 니 다.
 
  
=====v1=====
staticValue:父类静态变量
value:父类实例变量
=====v2=====
staticValue:父类静态变量
value:父类实例变量
=====v3=====
staticValue:子类静态变量
value:子类实例变量

  
결론 은 부모 클래스 를 호출 하 는 방법 이 냐, 하위 클래스 를 호출 하 는 방법 이 냐, 변수의 성명 유형 과 만 관계 가 있 고, 실례 화 된 유형 과 는 관계 가 없다.
값 전달 인지, 인용 전달 인지, 이 화제 에 대한 제 관점 은 값 전달 입 니 다. 스 택 에 저 장 된 내용 을 전달 하기 때 문 입 니 다. 기본 유형의 값 이 든 더미 에 있 는 대상 을 가리 키 는 지침 이 든 모두 인용 이 아 닌 값 입 니 다. 또한 값 전달 과정 에서 JVM 은 값 을 복사 한 다음 에 복 사 된 값 을 호출 방법 에 전달 합 니 다.
이런 방식 으로 우 리 는 아래 의 코드 를 살 펴 보 자.
 
  
public class ParamTest {

     public void change(int value)
     {
         value = 10;
     }

     public void change(Value value)
     {
         Value temp = new Value();
         temp.value = 10;
         value = temp;
     }

     public void add(int value)
     {
         value += 10;
     }

     public void add(Value value)
     {
         value.value += 10;
     }

     public static void main(String[] args)
     {
         ParamTest test = new ParamTest();
         Value value = new Value();
         int v = 0;
         System.out.println("v:" + v);
         System.out.println("value.value:" + value.value);
         System.out.println("=====change=====");
         test.change(v);
         test.change(value);
         System.out.println("v:" + v);
         System.out.println("value.value:" + value.value);
         value = new Value();
         v = 0;
         System.out.println("=====add=====");
         test.add(v);
         test.add(value);
         System.out.println("v:" + v);
         System.out.println("value.value:" + value.value);
     }
 }

 class Value
 {
     public int value;
 }

출력 결과:
 
  
v:0
value.value:0
=====change=====
v:0
value.value:0
=====add=====
v:0
value.value:10

우 리 는 change 방법 을 호출 할 때 우리 가 전달 하 는 것 이 대상 을 가리 키 는 지침 이 라 고 해도 최종 대상 의 속성 은 변 하지 않 는 것 을 보 았 다. 이것 은 change 방법 체 내 에 대상 을 새로 만 든 다음 에 '복 제 된 대상 을 가리 키 는 지침' 을 '새로운 대상' 을 가리 키 고 새로운 대상 의 속성 을 조정 하기 때문이다. 그러나'복사 전의 원래 대상 을 가리 키 는 지침' 은 여전히 '원래 대상' 을 가리 키 고 속성 은 변화 가 없다.
final/finally/finalize 의 차이 final 은 클래스, 구성원 변수, 방법 및 방법 매개 변 수 를 수식 할 수 있 습 니 다. final 수식 클래스 를 사용 하면 계승 할 수 없습니다. final 수식 방법 을 사용 하면 다시 쓸 수 없습니다. final 수식 변 수 를 사용 하면 한 번 만 할당 할 수 있 습 니 다.
final 선언 변수의 할당 시기 사용 하기:
1) 성명 을 정의 할 때 값 부여
2) 초기 화 블록 이나 정적 초기 화 블록 중
3) 구조 함수
다음 코드 보기:
 
  
class FinalTest
 {
     public static final String staticValue1 = "静态变量1";
     public static final String staticValue2;

     static
     {
         staticValue2 = "静态变量2";
     }

     public final String value1 = "实例变量1";
     public final String value2;
     public final String value3;

     {
         value2 = "实例变量2";
     }

     public FinalTest()
     {
         value3 = "实例变量3";
     }
 }

  
finally 는 보통 try... catch 와 함께 사용 하 는데 주로 자원 을 방출 하 는 데 사 용 됩 니 다.
다음 코드 를 살 펴 보 겠 습 니 다.
 
  
public class FinallyTest {

     public static void main(String[] args)
     {
         finallyTest1();
         finallyTest2();
         finallyTest3();
     }

     private static String finallyTest1()
     {
         try
         {
             throw new RuntimeException();
         }
         catch(Exception ex)
         {
             ex.printStackTrace();
         }
         finally
         {
             System.out.println("Finally语句被执行");
         }
         try
         {
             System.out.println("Hello World");
             return "Hello World";
         }
         catch(Exception ex)
         {
             ex.printStackTrace();
         }
         finally
         {
             System.out.println("Finally语句被执行");
         }
         return null;
     }

     private static void finallyTest2()
     {
         int i = 0;
         for (i = 0; i < 3; i++)
         {
             try
             {
                 if (i == 2) break;
                 System.out.println(i);
             }
             finally
             {
                 System.out.println("Finally语句被执行");
             }
         }
     }

     private static Test finallyTest3()
     {
         try
         {
             return new Test();
         }
         finally
         {
             System.out.println("Finally语句被执行");
         }
     }
 }

실행 결 과 는 다음 과 같 습 니 다.
 
  
java.lang.RuntimeException
    at sample.interview.FinallyTest.finallyTest1(FinallyTest.java:16)
    at sample.interview.FinallyTest.main(FinallyTest.java:7)
Finally语句被执行
Hello World
Finally语句被执行

Finally语句被执行

Finally语句被执行
Finally语句被执行
Test实例被创建
Finally语句被执行


순환 하 는 과정 에서 어떤 순환 에 대해 서 는 break 나 contine 을 호출 하 더 라 도 finally 가 실 행 됩 니 다.
finalize 는 주로 자원 을 방출 하 는 데 사용 되 며 GC 방법 을 호출 할 때 이 방법 이 호출 됩 니 다.
아래 의 예 시 를 보십시오.
 
  
class FinalizeTest
 {
     protected void finalize()
     {
         System.out.println("finalize方法被调用");
     }

     public static void main(String[] args)
     {
         FinalizeTest test = new FinalizeTest();
         test = null;
         Runtime.getRuntime().gc();
     }
 }

실행 결 과 는 다음 과 같 습 니 다.
 
  
finalize方法被调用

  
기본 유형 에 관 한 일 들
기본 유형 은 9 가지 로 나 뉘 는데 byte/short/int/long/float/double/boolean/void 를 포함 하고 모든 기본 유형 은 하나의 '포장 류' 에 대응 하 며 다른 기본 정 보 는 다음 과 같다.
 
  
. 基本类型:byte 二进制位数:8
. 包装类:java.lang.Byte
. 最小值:Byte.MIN_VALUE=-128
. 最大值:Byte.MAX_VALUE=127
. 基本类型:short 二进制位数:16
. 包装类:java.lang.Short
. 最小值:Short.MIN_VALUE=-32768
. 最大值:Short.MAX_VALUE=32767
. 基本类型:int 二进制位数:32
. 包装类:java.lang.Integer
. 最小值:Integer.MIN_VALUE=-2147483648
. 最大值:Integer.MAX_VALUE=2147483647
. 基本类型:long 二进制位数:64
. 包装类:java.lang.Long
. 最小值:Long.MIN_VALUE=-9223372036854775808
. 最大值:Long.MAX_VALUE=9223372036854775807
. 基本类型:float 二进制位数:32
. 包装类:java.lang.Float
. 最小值:Float.MIN_VALUE=1.4E-45
. 最大值:Float.MAX_VALUE=3.4028235E38
. 基本类型:double 二进制位数:64
. 包装类:java.lang.Double
. 最小值:Double.MIN_VALUE=4.9E-324
. 最大值:Double.MAX_VALUE=1.7976931348623157E308
. 基本类型:char 二进制位数:16
. 包装类:java.lang.Character
. 最小值:Character.MIN_VALUE=0
. 最大值:Character.MAX_VALUE=65535

  
기본 유형 에 대한 결론 (자바 면접 해 혹 에서 온 것) • 문자 접미사 표지 가 없 는 정 수 는 기본적으로 int 형식 이 고 문자 접미사 표지 가 없 는 부동 소수점 은 기본적으로 double 형식 입 니 다.
• 하나의 정수 값 이 int 형식 이 표시 할 수 있 는 범 위 를 초과 하면 접미사 'L' (대소 문 자 를 구분 하지 않 고 대문자 로 사용 하 는 것 을 권장 합 니 다. 소문 자의 L 과 아라비아 숫자 1 이 헷 갈 리 기 쉽 기 때 문 입 니 다) 을 늘 려 long 형 으로 표시 해 야 합 니 다.
• 'F' (대소 문자 구분 없 음) 접 두 사 를 가 진 정수 와 부동 소수점 은 모두 float 형식 이 고 'D' (대소 문자 구분 없 음) 접 두 사 를 가 진 정수 와 부동 소수점 은 모두 double 형식 입 니 다.
• 컴 파일 러 는 컴 파일 기간 에 byte, short, int, long, float, double, char 형 변수의 값 을 검사 하고 그들의 수치 범 위 를 초과 하면 오 류 를 보고 합 니 다.
• int 형 값 은 모든 수치 유형의 변 수 를 부여 할 수 있 습 니 다. long 형 값 은 long, float, double 형식의 변 수 를 부여 할 수 있 습 니 다. float 형 값 은 float, double 형식의 변 수 를 부여 할 수 있 고 double 형 값 은 double 형식 변수 에 만 부여 할 수 있 습 니 다.
  
기본 유형 간 의 전환 에 대해 아래 의 전환 은 무 손실 정밀도 의 전환 입 니 다.
• byte -> short • short -> int • char -> int • int -> long • float -> double 아래 의 전환 은 정밀도 손실:
• int -> float • long -> float • long -> double 은 이 를 제외 한 전환 은 불법 입 니 다.
날짜 와 관련 된 일 들 자바 에는 날짜 와 관련 된 두 가지 종류 가 있 습 니 다. 하 나 는 Date 이 고 하 나 는 Calendar 입 니 다. 아래 의 예 를 살 펴 보 겠 습 니 다.
 
  
public class DateTest {

     public static void main(String[] args) throws ParseException
     {
         test1();
         test2();
         test3();
     }

     private static void test1() throws ParseException
     {
         Date date = new Date();
         System.out.println(date);
         DateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
         System.out.println(sf.format(date));
         String formatString = "2013-05-12";
         System.out.println(sf.parse(formatString));
     }

     private static void test2()
     {
         Date date = new Date();
         System.out.println("Year:" + date.getYear());
         System.out.println("Month:" + date.getMonth());
         System.out.println("Day:" + date.getDate());
         System.out.println("Hour:" + date.getHours());
         System.out.println("Minute:" + date.getMinutes());
         System.out.println("Second:" + date.getSeconds());
         System.out.println("DayOfWeek:" + date.getDay());
     }

     private static void test3()
     {
         Calendar c = Calendar.getInstance();
         System.out.println(c.getTime());
         System.out.println(c.getTimeZone());
         System.out.println("Year:" + c.get(Calendar.YEAR));
         System.out.println("Month:" + c.get(Calendar.MONTH));
         System.out.println("Day:" + c.get(Calendar.DATE));
         System.out.println("Hour:" + c.get(Calendar.HOUR));
         System.out.println("HourOfDay:" + c.get(Calendar.HOUR_OF_DAY));
         System.out.println("Minute:" + c.get(Calendar.MINUTE));
         System.out.println("Second:" + c.get(Calendar.SECOND));
         System.out.println("DayOfWeek:" + c.get(Calendar.DAY_OF_WEEK));
         System.out.println("DayOfMonth:" + c.get(Calendar.DAY_OF_MONTH));
         System.out.println("DayOfYear:" + c.get(Calendar.DAY_OF_YEAR));
     }
 }

출력 결 과 는 다음 과 같 습 니 다.
 
  
Sat May 11 13:44:34 CST 2013
-05-11
Sun May 12 00:00:00 CST 2013
Year:113
Month:4
Day:11
Hour:13
Minute:44
Second:35
DayOfWeek:6
Sat May 11 13:44:35 CST 2013
sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=19,lastRule=null]
Year:2013
Month:4
Day:11
Hour:1
HourOfDay:13
Minute:44
Second:35
DayOfWeek:7
DayOfMonth:11
DayOfYear:131

주의해 야 할 것 은 Date 의 getxxx 방법 이 deprecated 로 바 뀌 었 기 때문에 우 리 는 가능 한 한 calendar. get 방법 으로 날짜 의 세부 정 보 를 얻 습 니 다.
또한 DateFormat 에 주의 하 십시오. 날짜 의 출력 을 포맷 할 수 있 을 뿐만 아니 라 역방향 으로 조작 하여 Format 에 맞 는 문자열 을 날짜 형식 으로 변환 할 수 있 습 니 다.

좋은 웹페이지 즐겨찾기