类变量(静态变量)

在类中定义的变量,加上static称为类变量,否则称为实例变量/普通变量。

性质:

  1. 类中使用static修饰的变量将会被所有同类共享。
  2. static类变量,在类加载时就生成了,不需要创建对象实例就可以访问(以该变量不是private修饰为前提)。

注意事项

  1. 什么时候需要使用类变量?

当我们需要让某个类的所有对象对共享一个变量时可以使用。

  1. 类变量与实例变量的区别:

类变量是该类的所有对象共享的,而实例变量时每个对象独享的。

  1. 类变量的生命周期随着类加载开始,随着类消亡而被销毁。

类方法(静态方法)

类似于类变量,就是在类中定义的方法前使用static修饰。

使用时不需要将类实例化,直接用类名.方法使用。

注意事项

  1. 类方法和普通方法一样,随着类加载而加载,将结构信息存在方法区
  2. 类方法中无this参数,不能使用与对象有关的关键字,如thissuper
  3. 类方法只能访问静态变量和静态方法。
  4. 普通成员方法可以访问静态方法和普通方法。

理解main方法

public static void main(String[] args){}

  1. main方法由JVM调用
  2. JVM需要调用类的main()方法,所以该方法的访问权限必须是public
  3. JVM在执行main()方法时不需要创建对象,所以该方法必须是static
  4. main方法会接受String类型的数组参数args,该数组中保存着执行java命令时传递给所运行的类的参数
  5. main方法中想要访问非静态的变量和方法需要先实例化再用。

代码块的使用

没有方法名的方法。使用格式:

static或者什么都不写 {
......
}

相当于另外一种形式的构造器,可以做初始化操作,在使用构造器之前会调 用代码块,也就是说优先级高于构造器内的代码。可以将多次出现的重复代码放到代码块中。

注:如果使用static修饰代码块,则总共只会调用一次。如果是普通代码块,则每创建一次这个类都会执行一次。

创建对象时,在类中的调用顺序:

  1. 调用静态代码块和静态属性初始化
  2. 调用普通代码块和普通属性初始化
  3. 调用构造方法

当创建一个子类对象时(继承父类),调用顺序为:

  1. 父类的静态代码块和静态属性
  2. 子类的静态代码块和静态属性
  3. 父类的普通代码块和普通属性
  4. 父类的构造方法
  5. 子类的普通..
  6. 子类的构造方法

final关键字

final可以修饰类、属性、方法和局部变量,final修饰的属性又叫做常量。

用法:

  1. 当不希望类被继承时。
  2. 当不希望父类的某个方法被子类覆盖或重写时。
  3. 当不希望类的某个属性的值被修改时。
  4. 当不希望某个局部变量被修改时。

注意事项

  1. final修饰的属性一般用XX_XX_XX命名(大写,字母间使用下划线隔开)

  2. final属性在定义时必须赋初值,赋值的位置可以在:

    • 定义时直接赋值

    • 在构造器中赋值(仅限非static)

    • 在代码块中赋值(static时使用静态代码块)

  3. 如果一个类已经是final类了,其中的属性和方法就不要用final修饰了

  4. final不能修饰构造器

  5. final往往与static一起使用,效率更高,不会导致类加载

  6. 包装类(Integer、Double、Float、Boolean等)都是使用final修饰的,不可被继承

抽象类

​ 当在父类中声明了一个方法,但是不知道该如何实现时,就可以不实现,而是把该方法声明为一个抽象方法,同时该类变成一个抽象类。

  1. 用abstract关键字来修饰一个类/方法时,这个类就叫做抽象类/方法
  2. 抽象类的价值更多作用在于设计,是设计者设计好后,让子类继承并实现抽象类
  3. 抽象类不能被实例化
  4. 抽象方法一定在抽象类中,但是抽象类不一定有抽象方法
  5. 如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,除非它自己也是抽象类
  6. 抽象方法不能使用private、final和static修饰,因为这三个关键字都与重写相违背(用这三个关键字修饰方法不许被修改)

例子:

abstract class Animal{
private String name;
private int age;
abstract public void eat(); //抽象类不能有主体"{}"
}

接口

接口就是给出一些没有实现的方法,封装到一起,当某个类要用时,根据具体情况把接口中的方法写出来。

java8之后,接口中可以有方法的具体实现,但是非静态方法需要使用default修饰。

接口中的方法都默认使用public abstract修饰,属性默认使用public static final修饰。

语法:

public interface 接口名{
// 属性
// 方法
void xxx();
default void XXX(){}
static void XXXX(){}
}

// 要用到接口时
class 类名 implements 接口{
// 属性
// 方法
}

注意事项

  1. 接口不能被实例化(同抽象类)
  2. 一个类可以同时实现多个接口

class X implements Y, Z {}

  1. 接口不能继承类,但是可以继承其他接口(接口与接口之间是继承关系,接口与类之间是实现关系)

interface A extends B, C {}

  1. 接口的修饰符只能是public和默认

接口与继承

​ 当子类继承父类时,自动拥有父类的功能。但因为一个子类只能继承一个父类,如果子类需要扩展功能,就可以通过实现接口的方式扩展。可以理解为实现接口是对java单继承机制的扩展。

内部类

一个类的内部又完整的嵌套了另一个类,被嵌套的类叫做内部类。

局部内部类

局部内部类定义在外部类的局部位置,通常在方法或代码块中,有类名。

特点

  1. 可以直接访问外部类的全部成员,包括私有
  2. 不能添加访问修饰符,因为局部内部类的地位相当于一个局部变量。但是可以用final修饰
  3. 作用域:在定义它的方法或代码块中
  4. 外部类想访问局部内部类的成员需要先new一个再访问
  5. 如果外部类中成员和局部内部类中成员重名,访问时使用就近原则,如果想访问外部类,可以使用外部类.this.成员访问

匿名内部类

​ 匿名内部类没有类名(但是底层实现的时候有名字),不仅是一个类,还是一个对象,所有它同时拥有类和对象的特性,可以当做实参直接传递。

特点与局部内部类类似。

语法:

类或接口 变量名 = new 类或接口(参数){
// 类体
};
变量名.方法名();
// -----------或者--------------
new 类或接口(参数){
// 类体
}.方法名();

成员内部类

成员内部类定义在外部类的成员位置,没有static修饰。其定位是一个类成员,可以添加任意修饰符。并且作用域为整个外部类体。

特点

假设Outer类中有一个名为Inner的成员内部类,当外部其他类想使用成员内部时:

Outer out = new Outer();

// 方法一
Outer.Inner inn = out.new Inner();

// 方法二:在Outer类中声明一个方法,可以返回Inner对象
class Outer{
.....;
public Inner getInnerInstance() {
return new Inner();
}
}
Outer.Inner inn = out.getInnerInstance();

其他使用方式跟其他内部类相同。

静态内部类

静态内部类是在成员内部类的基础上,有static修饰,有内部类和静态方法的全部特性。

当外部其他类想访问静态内部类时,因为是静态的,所以不需要实例化,通过类名直接访问:

Inner inn = new Outer.Inner();