zoukankan      html  css  js  c++  java
  • java高薪之路__001_类

    Java中内部类分四种:成员内部类、局部内部类、静态内部类和匿名内部类。
    要注意静态内部类的调用方式与其他不同,采用的是类似调用类中的静态属性、静态方法的方式

    Multi Level

    调用不同类中的相同的名字的属性
     1 /**
     2  * the output is:
     3  * x = 23
     4  * this.x = 1
     5  * ShadowTest.this.x = 0
     6  */
     7 public class ShadowTest {
     8     public int x = 0;
     9 
    10     class FirstLevel {
    11         public int x = 1;
    12 
    13         void methodInFirstLevel(int x) {
    14             System.out.println("x = " + x);
    15             System.out.println("this.x = " + this.x);
    16             System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);
    17         }
    18     }
    19 
    20     public static void main(String... args) {
    21         ShadowTest st = new ShadowTest();
    22         ShadowTest.FirstLevel fl = st.new FirstLevel();
    23         fl.methodInFirstLevel(23);
    24     }
    25 }
    View Code

    Inner Class

    成员内部类: 即作为外部类的一个成员存在,与外部类的属性、方法并列。上述的Multi Level也是成员内部类
    内部类作为外部类的成员,可以访问外部类的私有成员或属性
    用内部类定义在外部类中不可访问的属性。这样就在外部类中实现了比外部类的private还要小的访问权限
    注意:成员内部类中不能定义静态变量,但可以访问外部类的所有成员,内部类是一个编译时的概念,一旦编译成功,就会成为完全不同的两类。对于一个名为outer的外部类和其内部定义的名为inner的内部类。编译完成后出现outer.class和outer$inner.class两类
     1 /**
     2 *The output is: 0 2 4 6 8 10 12 14 
     3 */
     4 public class DataStructure {
     5     
     6     // Create an array
     7     private final static int SIZE = 15;
     8     private int[] arrayOfInts = new int[SIZE];
     9     
    10     public DataStructure() {
    11         // fill the array with ascending integer values
    12         for (int i = 0; i < SIZE; i++) {
    13             arrayOfInts[i] = i;
    14         }
    15     }
    16     
    17     public void printEven() {
    18         
    19         // Print out values of even indices of the array
    20         DataStructureIterator iterator = this.new EvenIterator();
    21         while (iterator.hasNext()) {
    22             System.out.print(iterator.next() + " ");
    23         }
    24         System.out.println();
    25     }
    26     
    27     interface DataStructureIterator extends java.util.Iterator<Integer> { } 
    28 
    29     // Inner class implements the DataStructureIterator interface,
    30     // which extends the Iterator<Integer> interface
    31     
    32     private class EvenIterator implements DataStructureIterator {
    33         
    34         // Start stepping through the array from the beginning
    35         private int nextIndex = 0;
    36         
    37         public boolean hasNext() {
    38             
    39             // Check if the current element is the last in the array
    40             return (nextIndex <= SIZE - 1);
    41         }        
    42         
    43         public Integer next() {
    44             
    45             // Record a value of an even index of the array
    46             Integer retValue = Integer.valueOf(arrayOfInts[nextIndex]);
    47             
    48             // Get the next even element
    49             nextIndex += 2;
    50             return retValue;
    51         }
    52     }
    53     
    54     public static void main(String s[]) {
    55         
    56         // Fill the array with integer values and print out only
    57         // values of even indices
    58         DataStructure ds = new DataStructure();
    59         ds.printEven();
    60     }
    61 }
    View Code

    Local Class

    局部内部类: 即在方法中定义的内部类,与局部变量类似,在局部内部类前不加修饰符public或private,其范围为定义它的代码块。
    注意:局部内部类中不可定义静态变量,可以访问外部类的局部变量(即方法内的变量),但是变量必须是final的

    在类外不可直接生成局部内部类(保证局部内部类对外是不可见的)。要想使用局部内部类时需要生成对象,对象调用方法,在方法中才能调用其局部内部类。通过内部类和接口达到一个强制的弱耦合,用局部内部类来实现接口,并在方法中返回接口类型,使局部内部类不可见,屏蔽实现类的可见性
     1 /**
     2 *output: First number is 1234567890
     3 * Second number is invalid
     4 */
     5 public class LocalClassExample {
     6   
     7     static String regularExpression = "[^0-9]";
     8   
     9     public static void validatePhoneNumber(
    10         String phoneNumber1, String phoneNumber2) {
    11       
    12         final int numberLength = 10;
    13         
    14         // Valid in JDK 8 and later:
    15        
    16         // int numberLength = 10;
    17        
    18         class PhoneNumber {
    19             
    20             String formattedPhoneNumber = null;
    21 
    22             PhoneNumber(String phoneNumber){
    23                 // numberLength = 7;
    24                 String currentNumber = phoneNumber.replaceAll(
    25                   regularExpression, "");
    26                 if (currentNumber.length() == numberLength)
    27                     formattedPhoneNumber = currentNumber;
    28                 else
    29                     formattedPhoneNumber = null;
    30             }
    31 
    32             public String getNumber() {
    33                 return formattedPhoneNumber;
    34             }
    35             
    36             // Valid in JDK 8 and later:
    37 
    38 //            public void printOriginalNumbers() {
    39 //                System.out.println("Original numbers are " + phoneNumber1 +
    40 //                    " and " + phoneNumber2);
    41 //            }
    42         }
    43 
    44         PhoneNumber myNumber1 = new PhoneNumber(phoneNumber1);
    45         PhoneNumber myNumber2 = new PhoneNumber(phoneNumber2);
    46         
    47         // Valid in JDK 8 and later:
    48 
    49 //        myNumber1.printOriginalNumbers();
    50 
    51         if (myNumber1.getNumber() == null) 
    52             System.out.println("First number is invalid");
    53         else
    54             System.out.println("First number is " + myNumber1.getNumber());
    55         if (myNumber2.getNumber() == null)
    56             System.out.println("Second number is invalid");
    57         else
    58             System.out.println("Second number is " + myNumber2.getNumber());
    59 
    60     }
    61 
    62     public static void main(String... args) {
    63         validatePhoneNumber("123-456-7890", "456-7890");
    64     }
    65 }
    View Code

     Static Class

     1 package learn.JavaBasics.Class;
     2 
     3 public class Outer {
     4     private static int i=1;
     5     private int j=10;
     6     
     7     public static void outer_f1(){
     8         System.out.println("This is outer class");
     9     }
    10     
    11     public void outer_f2() {
    12         System.out.println("This is outer class");
    13     }
    14     
    15     static class Inner {
    16         static int inner_i=100;
    17         int inner_j = 200;
    18         
    19         static void inner_f1() {
    20             System.out.println("Outer.i:"+i);//静态内部类只能访问外部类的静态成员
    21             outer_f1();//包括静态变量和静态方法
    22         }
    23         
    24         void inner_f2() {
    25             
    26         }
    27     }
    28     
    29     public void outer_f3(){
    30         System.out.println(Inner.inner_i);//外部类访问内部类的静态成员:内部类.静态成员
    31         Inner inner = new Inner();
    32         inner.inner_f2();
    33     }
    34 
    35     public static void main(String[] args) {
    36         // TODO Auto-generated method stub
    37         new Outer().outer_f3();
    38         
    39         new Outer.Inner().inner_f2();//匿名调用内部的静态类
    40     }
    41 
    42 }
    View Code
    静态内部类: 静态内部类定义在类中,任何方法外,用static定义。
    注意:静态内部类中可以定义静态或者非静态的成员,静态内部类可以用public,protected,private修饰

    Anonymous Class

    A a = new A(), a就是类名,如果不需要类名a就可以调用类A中的方法,则是匿名类, 如:new A().toString();
    还有接口
     1 public class HelloWorldAnonymousClasses {
     2   
     3     interface HelloWorld {
     4         public void greet();
     5         public void greetSomeone(String someone);
     6     }
     7   
     8     public void sayHello() {
     9         
    10         class EnglishGreeting implements HelloWorld {
    11             String name = "world";
    12             public void greet() {
    13                 greetSomeone("world");
    14             }
    15             public void greetSomeone(String someone) {
    16                 name = someone;
    17                 System.out.println("Hello " + name);
    18             }
    19         }
    20       
    21         HelloWorld englishGreeting = new EnglishGreeting();
    22         
    23         HelloWorld frenchGreeting = new HelloWorld() {
    24             String name = "tout le monde";
    25             public void greet() {
    26                 greetSomeone("tout le monde");
    27             }
    28             public void greetSomeone(String someone) {
    29                 name = someone;
    30                 System.out.println("Salut " + name);
    31             }
    32         };
    33         
    34         HelloWorld spanishGreeting = new HelloWorld() {
    35             String name = "mundo";
    36             public void greet() {
    37                 greetSomeone("mundo");
    38             }
    39             public void greetSomeone(String someone) {
    40                 name = someone;
    41                 System.out.println("Hola, " + name);
    42             }
    43         };
    44         englishGreeting.greet();
    45         frenchGreeting.greetSomeone("Fred");
    46         spanishGreeting.greet();
    47     }
    48 
    49     public static void main(String... args) {
    50         HelloWorldAnonymousClasses myApp =
    51             new HelloWorldAnonymousClasses();
    52         myApp.sayHello();
    53     }            
    54 }
    View Code

    类中的对象的初始化顺序

     1 public class InitializeDemo {
     2     private static int k = 1;
     3     private static InitializeDemo t1 = new InitializeDemo("t1");
     4     private static InitializeDemo t2 = new InitializeDemo("t2");
     5     private static int i = print("i");
     6     private static int n = 99;
     7     static {
     8         print("静态块");
     9     }
    10     private int j = print("j");
    11     {
    12         print("构造块");
    13     }
    14     public InitializeDemo(String str) {
    15         System.out.println((k++) + ":" + str + "   i=" + i + "    n=" + n);
    16         ++i;
    17         ++n;
    18     }
    19     public static int print(String str) {
    20         System.out.println((k++) + ":" + str + "   i=" + i + "    n=" + n);
    21         ++n;
    22         return ++i;
    23     }
    24     public static void main(String args[]) {
    25         new InitializeDemo("init");
    26     }
    27 }
    View Code

    1.静态属性和静态代码块都是在类加载的时候初始化和执行,两者的优先级别是一致的,
    且高于非静态成员,执行按照编码顺序。
    2.非静态属性和匿名构造器在所有的构造方法之前执行,两者的优先级别一致,执行按照编码顺序。
    3.以上执行完毕后执行构造方法中的代码。

    读者仔细揣摩上面三条句子,也就是Java对象初始化的顺序,也就明白以上程序的输出结果为什么如下:

    1:j i=0 n=0
    2:构造块 i=1 n=1
    3:t1 i=2 n=2
    4:j i=3 n=3
    5:构造块 i=4 n=4
    6:t2 i=5 n=5
    7:i i=6 n=6
    8:静态块 i=7 n=99
    9:j i=8 n=100
    10:构造块 i=9 n=101
    11:init i=10 n=102

    如果还是没有明白,就看下面详解,一下详解的顺序就是按照上文的核心理念的顺序来执行的(建议读者把自己带入JVN的世界里,跟着JVM一步一步往下面走):

    1.运行main方法的时候,JVM会调用ClassLoader来加载InitializeDemo类,那么一起源于这次加载。
    2.上面有四个静态属性,所以会按顺序逐一初始化这四个静态属性。
    3.private static int k = 1; 此时将k初始化为1。
    4.private static InitializeDemo t1 = new InitializeDemo("t1");创建InitializeDemo对象,
      那么按照核心理念中的顺序,先执行private int j = print("j");,打印出j,然后执行构造
      块,最后执行构造方法。
    5.private static InitializeDemo t2 = new InitializeDemo("t2");同步骤4。
    6.private static int i = print("i");打印i。
    7.private static int n = 99;直到这一步,n才被赋值为99,之前是从默认的0开始++的。
    8.静态属性初始化完毕,代码走到静态块,打印出静态块,此时n=99。
    9.静态属性和静态块执行完毕,然后执行main方法中的代码new InitializeDemo("init");
    10.main方法中创建对象,先初始化非静态属性,private int j = print("j");打印j,
       然后执行构造块,最后执行构造方法。
    不知道我解说清楚了没有,只要把握住核心理念,碰到在复杂的问题也都不会怕了。
    用一个公式概括一下Java对象初始化执行优先级别:
    (静态属性=静态代码块)> (非静态属性 = 构造块)> 构造方法
    总结一下核心理念:

    1.静态只在类加载的时候执行,且执行一次。
    2.非静态只在实例化的时候执行,且每次实例化都执行。
    3.静态在非静态之前执行。
    4.静态属性和静态块的执行顺序取决于编码顺序,对它们一视同仁。
    5.非静态属性和构造块的执行顺取决于编码顺序,对它们也一视同仁。
    6.最后执行构造方法。

     上面的总结有点绕对吧,问题进一步简化的话,就更好理解了:

    读者将静态代码块视为一个静态属性,将构造块视为一个非静态属性,那么问题简化到了这种路线“静态属性-->非静态属性-->构造方法“
  • 相关阅读:
    HDU 4611 Balls Rearrangement 数学
    Educational Codeforces Round 11 D. Number of Parallelograms 暴力
    Knockout.Js官网学习(简介)
    Entity Framework 关系约束配置
    Entity Framework Fluent API
    Entity Framework DataAnnotations
    Entity Framework 系统约定配置
    Entity Framework 自动生成CodeFirst代码
    Entity Framework CodeFirst数据迁移
    Entity Framework CodeFirst尝试
  • 原文地址:https://www.cnblogs.com/hangtt/p/4853537.html
Copyright © 2011-2022 走看看