java基础5

来源:互联网 发布:java web mvc四层架构 编辑:程序博客网 时间:2024/05/21 10:30

Advanced Language Features 


知识点:一. static修饰符
          
    属性                 静态属性
    方法                 静态方法
    匿名代码块(初始化)     静态代码块
                        静态导入

            static修饰符可以用来修饰类的成员变量、成员方法和代码块。
            . 用static修饰的成员变量表示静态变量,可以直接通过类名来访问;
            . 用static修饰的成员方法表示静态方法,可以直接通过类名来访问;
            . 用static修饰的程序代码表示静态代码块,当Java虚似机加载类时,就会执行该代码块;

            被static所修饰的成员变量和成员方法表明归某个类所有,它不依赖于类的特定实例,被类的所有实例共享。


            1. static 变量


               成员变量:定义在类里面、方法外面的变量, 分两种:
                         a. 实例变量;
                         b. 静态变量;形式和实例变量类似,在实例变量前面加static关键字;

               static变量和实例变量的区别:
               . static变量对于每个类而言在内存中只有一个,能被类的所有实例所共享;实例变量对于每个类的
  每个实例都有一份,它们之间互不影响;
               . Java虚拟机在加载类的过程中为static变量分配内存,实例变量在加载完类后创建对象时分配内存;
               . static变量可以直接通过类名访问,实例变量通过引用类型变量访问;

               举例: public class Counter {
                             public int count1 = 0;
                             public static int count2 = 0;

                             public static void main(String[] args) {
                                    Counter counterA = new Counter();
                                    Counter counterB = new Counter();
                                    counterA.count1++;
                                    counterA.count2++;
                                    counterB.count1++;
                                    counterB.count2++;
                             }
                      }

               练习:统计一个类创建实例的个数;
                              
            2. static 方法

               成员方法分为静态方法和实例方法。用static修饰的方法叫静态方法,或类方法。静态方法也和
  静态变量一样,不需要创建类的实例,可以直接通过类名来访问。

               public class Sample1 {
                     public static int add(int x, int y) {
                            return x+y;
                     }
               }

               public class Sample2 {
                     public void method() {
                            int result = Sample1.add(1,2);
                            System.out.println("result= " + result);
                     }
               }

               a. static方法可以直接访问所属类的实例变量和实例方法,直接访问所属类的静态变量和静态方法;

                  注:1) 不能使用this关键字;
                      2) 不能使用super关键字,super关键字用来访问当前实例从父类中继承的方法和属性。
 super关键字与类的特定实例相关;
                      3) 静态方法必须被实现。静态方法用来表示某个类所特有的功能,这种功能的实现不依赖于
 类的具体实例,也不依赖于它的子类。既然如此,当前类必须为静态方法提供实现。

               b. 父类的静态方法不能被子类覆为非静态方法。以下代码编译出错。

                  public class Base {
                         public static void method() {}
                  }

                  public class Sub extends Base {
                         public  void method() {}//编译出错
                  }

               c. 父类的非静态方法不能被子类覆盖为静态方法;

            3. static 代码块                  

               类中可以包含静态代码块,它不存于任何方法中。在Java虚拟机中加载类时会执行这些静态代码块。
  如果类中包含多个静态代码块,那么Java虚拟机将按照它们在类中出现的顺序依次执行它们,每个
  静态代码块只会被执行一次。(思考:什么时候JVM对一个类进行类加载)

               public class Sample {
                   static int i = 5;
                   static {//第一个静态代码块
                          System.out.println("First Static code i="+i++);
                   }
                   static {//第二个静态代码块
                          System.out.println("Second Static code i="+i++);
                   }
                   public static void main(String[] args) {
                          Sample s1 = new Sample();
                          Sample s2 = new Sample();
                          System.out.println("At last, i= "+i);
                   }
               }

               类的构造方法用于初始化类的实例,而类的静态代码块则可用于初始化类,给类的静态变量赋初始值。

               静态代码块与静态方法一样,也不能直接访问类的实例变量和实例方法,而必须通过实例的引用来
  访问它们。

//Student s = new Student();
   new一个对象的时候JVM都做了那些事情:
1.之前没有进行类加载
1.类加载,(java -cp xx.xx.xx,Class.forName/load)
      同时初始化类中静态的属性(赋默认值)
2.执行静态代码块
//如果之前做过类加载,从第三步开始执行
      3.分配内存空间,同时初始化非静态的属性(赋默认值)
4.调用父类构造器
5.父类构造器执行完后,如果自己声明属性的同时有显示的赋值,那么进行显示赋值把默认值覆盖
6.执行匿名代码块
7.执行构造器
8.返回内存地址

例子:
package com.briup.ch06;

public class Test {
public static void main(String[] args) {

A a = new B();
}
}

class A{
protected String name = "lisi";
public A() {
System.out.println("父类构造器A");
System.out.println("父类构造器A中调用test方法开始,由于子类重写过test方法所以这里执行
子类的test方法");
test();
System.out.println("父类构造器A中调用test方法结束");
}
public void test(){

}
}

class B extends A{
private String name = "tom";
{
System.out.println("子类匿名代码块中:"+name);
}
public B() {
System.out.println("子类构造器B");
}
public void test(){

System.out.println("test方法中:this.name="+this.name);
System.out.println("test方法中:super.name="+super.name);

}
}

打印结果:
父类构造器A                            //子类构造器调用父类构造器
父类构造器A中调用test方法开始,由于子类重写过test方法所以这里执行子类的test方法
test方法中:this.name=null    //这个时候父类构造器还没有执行完 所以子类中的属性不会显示赋值 
所以只有初始的默认值null
test方法中:super.name=lisi   //这个时候父类构造器开始调用 了 所以父类中的属性已经有了显示赋的
值了
父类构造器A中调用test方法结束
子类匿名代码块中:tom           //这个时候父类构造器已经调用结束 所以子类中的属性已经有了显示
赋的值了
子类构造器B

结论:  子类中的属性的显示赋值的时机 是在 父类构造器执行完之后和子类的匿名代码块执行之前的某个
时候

2.之前已经进行了类加载
1.分配内存空间,同时初始化非静态的属性(赋默认值)
2.调用父类构造器
3.父类构造器执行完后,如果自己声明属性的同时有显示的赋值,那么进行显示赋值把默认值覆盖
4.执行匿名代码块
5.执行构造器
6.返回内存地址
      练习例子:StaticTest.java  StaticTest2.java


4. 静态导入 静态方法或者变量

            import static
静态导入也是JDK5.0引入的新特性。
要使用静态成员(方法和变量)我们必须给出提供这个静态成员的类。使用静态导入可以使被导入类的静态变量
和静态方法在当前类中可以直接使用,使用这些静态成员无需再在前面写上他们所属的类名。
//例如:
import static java.lang.Math.random;
import static java.lang.Math.PI;;

public class Test {

public static void main(String[] args) {
//之前是需要Math.random()调用的
System.out.println(random());
System.out.println(PI);

}
}

        二. final修改符 类   方法    变量(属性 局部变量)
        静态属性     非静态 
        局部变量

               final具有"不可改变的"含义,它可以修饰非抽象类、非抽象成员方法和变量。
               . 用final修饰的类不能被继承,没有子类;
               . 用final修饰的方法不能被子类的方法覆盖;
               . 用final修饰的变量表示常量,只能被赋一次值;

               final不能用来修饰构造方法,因为"方法覆盖"这一概念仅适用于类的成员方法,而不适用于类的构造
  方法,父类的构造方法和子类的构造方法之间不存在覆盖关系. 因此用final修饰构造方法是无意义的。
  父类中用private修饰的方法不能被子类的方法覆盖,因此private类型的方法默认是final类型的。

               1. final类

                  继承关系的弱点是打破封装,子类能够访问父类的方法,而且能以方法覆盖的方式修改实现细节。
 在以下情况下,可以考虑把类定义为final类型,使得这个类不能被继承。

                  . 子类有可能会错误地修改父类的实现细节;
                  . 出于安全,类的实现细节不允许有任何改动;
                  . 在创建对象模型时,确信这个类不会再被扩展;

                  例如JDK中java.lang.String类被定义为final类型;

               2. final方法;
 
                  某些情况下,出于安全原因,父类不允许子类覆盖某个方法, 此时可以把这个方法声明为final类型。
 例如在java.lang.Object类中,getClass()方法为final类型。

               3. final变量:
 final修饰的属性(成员变量)赋值的位置:
非静态的成员变量
1.声明的同时
2.匿名代码块
3.构造器(类中出现的所有构造器)

静态的成员变量
1.声明的同时

2.static代码块  


                  a. final可以修饰静态变量、实例变量、局部变量;
                  b. final变量都必须显示初始化,否则会导致编译错误;
                     1) 静态变量,定义变量时进行初始化或者static代码块中赋值;
                     2) 实例变量,可以在定义变量时,或者在构造方法中进行初始化;
                  c. final变量只能赋一次值。

                     public class Sample {
                            private final int var1 = 1;
                            public Sample() {
                                 var1 = 2;                //编译出错,不允许改变var1实例变量的值;
                            }

                            public void method(final int param) {
                                 final int var2 = 1;         
                                 var2++;                  //编译出错,不允许改变var2局部常量的值
                                 param++;                 //编译出错,不允许改变final类型参数的值;
                            }
                     }

                     public class Sample {
                            final int var1;               //定义var1实例常量
                            final int var2 = 0;           //定义并初始化var2实例常量
   
                            Sample() {
                                  var1 = 1;               //初始化var1实例常量
                            }

                            Sample(int x) {
                                  var1 = x;                //初始化var1实例常量
                            }
                     }       

   练习 FinalTest.java              

        三. abstract修饰符

            可用来修饰类和成员方法。
            . 用abstract修饰的类表示抽象类,抽象类不能实例化,即不允许创建抽象类本身的实例。没有用
abstract修饰的类称为具体类,具体类可以被实例化。
            . 用abstract修饰的方法表示抽象方法,抽象方法没有方法体。抽象方法用来描述系统具有什么功能,
但不提供具体的实现。
              没有abstract修饰的方法称为具体方法,具体方法具有方法体。
            
            语法规则;
            1) 抽象类中可以没有抽象方法,但包含了抽象方法的类必须被定义为抽象类;
            2) 没有抽象构造方法,也没有抽象静态方法;
            3) 抽象类中可以有非抽象的构造方法;
            4) 抽象类及抽象方法不能被final修饰符修饰。
            5) 抽象类中可以有main,也可以static修饰的方法和属性
            6) 抽象类中,可以有构造器,但是不能用来创建对象

            抽象类不允许实例化:思考原因?
   练习 AbstractTest.java

        四. 接口

            接口使用的目的:解决多重继承问题;例如Fish类继承Animal类,表明Fish是一种动物,但鱼同样也是一种
食物,如何表示这种关系呢? 由于Java语言不支持一个类有多个直接的父类,因此无法用继承关系来描述
鱼既是一种食物,又是一种动物,为了解决这一问题,Java语言引入接口类型,简称接口。一个类只能有
一个直接的父类,但是可以实现多个接口。 采用这种方式,Java语言对多继承提供了有力的支持。

            1. 接口是抽象类的另外一种形式

               抽象类抽象到极致就是接口,抽象类可存在有方法体的方法,接口中的方法全部为抽象方法;

            2. 接口中的所有方法均是抽象方法, 默认都是public、abstract类型的;

               public interface A {
                      void method1();                //合法,默认为public、abstract类型
                      public abstract void method2();//合法,显示声明为public、abstract类型

            3. 接口中的成员变量默认都是public, static, final类型,必须被显式初始化;
               public interface A {
                      int CONST = 1;                 //合法,CONST默认为public, static, final类型
                      public static final int OPAQUE = 1;  //合法,显示声明为public static final 类型
               }
 
            4. 接口中只能包含public, static, final类型成员变量和public、abstract类型的成员方法;
            5. 接口中没有构造方法,不能被实例化。
            6. 一个类只能继承一个直接的父类,但能实现多个接口。

            抽象类和接口比较:

            1. 相同点:
               a. 都不能被实例化;
               b. 都能包含抽象方法;
            2. 不同点;
               a. 抽象类中可以为部分方法提供默认的实现,从而避免子类中重复实现它们,提高代码的可重用性,
  而接口中只能包含抽象方法;
               b. 一个类只能继承一个直接的父类,这个父类有可能是抽象类;但一个类可以实现多个接口,这是接
  口的优势所在。
   
   练习:InterfaceTest.java InterfaceTest2.java
        五. 访问控制

            面向对象的基本思想之一是封装实现细节并且公开方法。Java语言采用访问控制修饰符来控制类及类的方
法和变量的访问
            权限,从而只向使用者暴露方法,但隐藏实现细节。访问控制分4种级别

            访问级别       访问控制修饰符        同类       同包       子类      不同的包
            公开级别:       public                 y         y          y           y
            受保护           protected             y          y        y
            默认           没有访问控制符           y          y
            私有             private               y

            成员变量、成员方法和构造方法可以处于4个访问级别中的一个;
            顶层类只可以处于公开或默认访问级别;

   注意:protected和default都有包访问权限(同包下可以访问)
原创粉丝点击