final修饰类,修饰方法,修饰变量的特点

final class Test{// 修饰类,类不能被继承
    public static void main(String[] args){
        final Test test = new Test();// 修饰对象,对象不能被修改
        final int a = 1;// 修饰变量,变量就变成了常量,只能被赋值一次
    }
    final public void fun(){}// 修饰方法,方法不能被重写
}

package,import,class之间顺序关系

package > import > class

package:只能有一个

import:可以有多个

class:可以有多个,以后建议是一个。(因为每一个类是一个独立的单元)

Java中的修饰符

类修饰符

public(访问控制符),将一个类声明为公共类,他可以被任何对象访问,一个程序的主类必须是公共类。

abstract 将一个类声明为抽象类,没有实现的方法,需要子类提供方法实现。

final 将一个类生命为最终(即非继承类),表示他不能被其他类继承。

friendly 默认的修饰符,只有在相同包中的对象才能使用这样的类。

成员变量修饰符

public(公共访问控制符)指定该变量为公共的,他可以被任何对象的方法访问。

private(私有访问控制符)指定该变量只允许自己的类的方法访问,其他任何类(包括子类)中的方法均不能访问。

protected(保护访问控制符)指定该变量可以别被自己的类和子类访问。在子类中可以覆盖此变量。

friendly 在同一个包中的类可以访问,其他包中的类不能访问。

final 最终修饰符,指定此变量的值不能变。

static(静态修饰符)指定变量被所有对象共享,即所有实例都可以使用该变量。变量属于这个类。

transient(过度修饰符)指定该变量是系统保留,暂无特别作用的临时性变量。

volatile(易失修饰符)指定该变量可以同时被几个线程控制和修改。

方法修饰符

public(公共控制符)指定该方法为公共的,他可以被任何对象的方法访问。

private(私有控制符)指定此方法只能有自己类等方法访问,其他的类不能访问(包括子类)

protected(保护访问控制符)指定该方法可以被它的类和子类进行访问。

final 指定该方法不能被重载。

static 指定不需要实例化就可以激活的一个方法。

synchronize 同步修饰符,在多个线程中,该修饰符用于在运行前,对他所属的方法加锁,以防止其他线程的访问,运行结束后解锁。

native 本地修饰符。指定此方法的方法体是用其他语言在程序外部编写的。

内部类

在Java中,根据定义的位置和方式不同,主要有四种内部类:

  • 静态内部类
  • 成员内部类
  • 方法内部类
  • 匿名内部类

静态内部类

静态内部类与静态变量和静态方法定义的位置一样,也带有static关键字,只是它定义的是类,示例代码如下:

public class Outer {
    private static int shared = 100;
    public static class StaticInner {
        public void innerMethod(){
            System.out.println("inner " + shared);
        }
    }
    public void test(){
        StaticInner si = new StaticInner();
        si.innerMethod();
    }
}

外部类为Outer,静态内部类为StaticInner,带有static修饰符。语法上,静态内部类除了位置放在别的类内部外,它与一个独立的类差别不大,可以有静态变量、静态方法、成员方法、成员变量、构造方法等。

静态内部类与外部类的联系也不大(与后面其他内部类相比)。它可以访问外部类的静态变量和方法,如innerMethod直接访问shared变量,但不可以访问实例变量和方法。

成员内部类

成员内部类没有static修饰符,少了一个static修饰符,但含义却有很大不同,示例代码如下:

public class Outer {
    private int a = 100;
    public class Inner {
        public void innerMethod(){
            System.out.println("outer a " +a);
            Outer.this.action();
        }
    }
    private void action(){
        System.out.println("action");
    }
    public void test(){
        Inner inner = new Inner();
        inner.innerMethod();
    }
}

Inner就是成员内部类,与静态内部类不同,除了静态变量和方法,成员内部类还可以直接访问外部类的实例变量和方法,如innerMethod直接访问外部类私有实例变量a。成员内部类还可以通过"外部类.this.xxx"的方式引用外部类的实例变量和方法,如Outer.this.action(),这种写法一般在重名的情况下使用,没有重名的话,"外部类.this."是多余的。

方法内部类

内部类还可以定义在一个方法体中,示例代码如下所示:

public class Outer {
    private int a = 100;
    public void test(final int param){
        final String str = "hello";
        class Inner {
            public void innerMethod(){
                System.out.println("outer a " +a);
                System.out.println("param " +param);
                System.out.println("local var " +str);
            }
        }
        Inner inner = new Inner();
        inner.innerMethod();
    }
}

类Inner定义在外部类方法test中,方法内部类只能在定义的方法内被使用。如果方法是实例方法,则除了静态变量和方法,内部类还可以直接访问外部类的实例变量和方法,如innerMethod直接访问了外部私有实例变量a。如果方法是静态方法,则方法内部类只能访问外部类的静态变量和方法。

方法内部类还可以直接访问方法的参数和方法中的局部变量,不过,这些变量必须被声明为final,如innerMethod直接访问了方法参数param和局部变量str。

匿名内部类

匿名内部类没有名字,在创建对象的同时定义类,语法如下:

new 父类(参数列表) {
   //匿名内部类实现部分
}

或者

new 父接口() {
   //匿名内部类实现部分
}

匿名内部类是与new关联的,在创建对象的时候定义类,new后面是父类或者父接口,然后是圆括号(),里面可以是传递给父类构造方法的参数,最后是大括号{},里面是类的定义。

public class Outer {
    public void test(final int x, final int y){
        Point p = new Point(2,3){
            public double distance() {
                return distance(new Point(x,y));
            }
        };
       System.out.println(p.distance());
    }
}

创建Point对象的时候,定义了一个匿名内部类,这个类的父类是Point,创建对象的时候,给父类构造方法传递了参数2和3,重写了distance()方法,在方法中访问了外部方法final参数x和y。

匿名内部类只能被使用一次,用来创建一个对象。它没有名字,没有构造方法,但可以根据参数列表,调用对应的父类构造方法。它可以定义实例变量和方法,可以有初始化代码块,初始化代码块可以起到构造方法的作用,只是构造方法可以有多个,而初始化代码块只能有一份。

因为没有构造方法,它自己无法接受参数,如果必须要参数,则应该使用其他内部类。

与方法内部类一样,匿名内部类也可以访问外部类的所有变量和方法,可以访问方法中的final参数和局部变量。

代码块的分类

在Java中,使用{}括起来的代码被称为代码块。

  • 局部代码块

    在方法中出现;限定变量生命周期,及早释放,提高内存利用率

  • 构造代码块 (初始化块)

    在类中方法外出现;多个构造方法方法中相同的代码存放到一起,每次调用构造都执行,并且在构造方法前执行

  • 静态代码块

    在类中方法外出现,并加上static修饰;用于给类进行初始化,在加载的时候就执行,并且只执行一次。

class Test 
{
    static{
        System.out.println("Test静态代码块");
    }
    public static void main(String[] args) 
    {
        System.out.println("我是main方法");

        Code p1 = new Code();
        Code p2 = new Code();
    }
}
class Code
{
    static {
        System.out.println("Code中的静态代码块");
    }
    {
        System.out.println("Code中构造代码块");
    }
    public Code(){
        System.out.println("Code 的构造方法");
    }
}
/* 结果为
* Test静态代码块
* 我是main方法
* Code中的静态代码块
* Code中构造代码块
* Code 的构造方法
* Code中构造代码块
* Code 的构造方法
 */