static
作用范围
static不能修饰局部变量和构造器,可以修饰成员变量,成员方法,代码块,内部类,
类变量和类方法
类变量
在类里 public static int count = 0;这样的就是类变量,重点在于static关键词,使得同一个类的所有的对象(实例)都共享
类变量可以通过类名.类变量名访问或对象名.类变量名,推荐前一种(不违背访问修饰符的前提下)
实例变量不能通过类名.类变量名方式访问
类变量在类加载时就出初始化了,即使没有创建对象,只要类加载了,就可以使用类变量了
类变量的生命周期是随类加载开始,随着类消亡而销毁
类方法
访问修饰符 static 数据返回类型 方法名(){}
调用:类名.类方法名或者对象名.类方法名
普通方法不能够通过类名.对象名的方式调用
类方法的使用场景:在不创建实例的情况下就可以调用某个方法(即当做工具类来使用),在实际开发中,把一些通用的方法设计成静态方法,这样可以直接使用
类方法和普通方法都是随着类的加载而加载,将结构信息储存在方法区
类方法不允许使用和对象有关的关键字,比如this和super,普通方法可以用
类方法无法通过继承来重写
类方法中只能访问静态变量或者静态方法,普通的都可以访问
理解main方法
java虚拟机需要调用类的main方法,所以该方法的访问权限必须是public
java虚拟机在执行main()方法,所以该方法必须是static
该方法接受String类型的数组参数,该数组中保存执行java命令时传递给所运行的类的参数
java 执行的程序 参数1 参数2 参数3 (java Hello.java 你好 你好 你好)-
在main()方法中,我们可以直接调用main方法所在类的静态方法或静态属性
但是,不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员
代码块
基本介绍
代码块又称初始化块,属于类中的成员,类似于方法,将逻辑语句封装在方法体内,通过{}包围起来。
但和方法不同,没有方法名,没有返回,没有参数,只有方法体,而且不用通过对象或类显式调用,而是加载类时,或创建对象时隐式调用
基本语法
[修饰符]{};
修饰符可选,要写的话,也只能写static
代码块分为两类,有static的叫静态代码块,没有static修饰的,叫普通代码块
逻辑语句可以为任何逻辑语句
;可以写也可以不写
作用
另一种形式的构造器,可以做初始化的操作
不管调用哪个构造器,都会先调用代码块,代码块调用的顺序会高于构造器
场景:如果多个构造器中都有重复的语句,可以抽取到初始化块中,提高代码的重用性
细节
static代码块也叫静态代码块,作用就是对类进行初始化,而且它会随着类的加载而执行,并且只会执行一次,如果是普通代码块,没创建一个对象,就执行
普通的代码块,在创建对象实例时,会被隐式的调用,被创建一次,就会调用一次。如果只是使用类的静态成员时,普通代码块并不会执行
创建一个对象时,在一个类中的调用顺序是(详细对象与类关于创建过程的详细解释)
- 调用静态代码块和静态属性初始化(都有按照定义顺序调用)
- 调用普通代码块和普通属性的初始化(都有按照定义顺序调用)
- 调用构造方法
- 构造器的最前面其实隐含了super()和调用普通代码块(调用和初始化是两回事)
静态代码块只能调用静态成员,普通代码块可以调用任意成员
final关键字
作用域
final 可以修饰类,属性,方法和局部变量//属性其实就是一种局部变量
功能
类不能被继承
方法不能被重写
属性的值不能被修改
注意事项和细节
final修饰的属性又叫常量,用XX_XX_XX来命名
final修饰的属性,必须赋初值,并且以后不能再修改,赋值可以在如下位置之一
- 定义时,public final double TAX_RATE = 0.08
- 在构造器中
- 在代码块中
如果final修饰的属性是静态的,则初始化的位置只能是
- 定义时
- 在静态代码块,不能在构造器中赋值
final类不能继承,但是可以实例化对象
如果类不是final类,但是含有final方法,则该方法虽然不能重写,但是可以被继承
一般来说,如果一个类已经是final类了,就没有必要再将方法修饰成final方法
final不能修饰构造器
final和static往往搭配处理,效率更高,底层编译器做了优化处理
包装类(Integer,Double,Float,Boolean)等都是final,String也是final类
抽象类
当父类的某些方法,需要声明,但是又不确定如何实现时,可以将其声明为抽象方法,那么这个类就是抽象类,抽象类是为了代码复用
概念
所谓抽象方法就是没有实现的方法
所谓没有实现就是没有方法体
当一个类中存在抽象方法的时候,需要将该类声明为abstract类
一般来说,抽象类会被继承,由子类来实现抽象方法
语法
访问修饰符 abstract 类名{}
访问修饰符 abstract 返回类型 方法名(参数列表);//没有方法体
继承的类需要重写方法(加上方法体)或者继承的子类也是abstract类
注意事项和细节
抽象类不能被实例化
抽象类不一定要包含abstract 方法,抽象类可以没有抽象方法
抽象类可以作为编译类型,但是不能作为运行类型
一旦类中包含了abstract方法,那么这个类必须声明为abstract
abstract只能修饰类和方法,不能修饰属性和其他的
抽象类还是类,可以有任意成员
抽象方法不能有方法体
如果一个类继承了抽象类,那么它必须实现抽象类的所有抽象方法,除非它自己 也声明为abstract类
抽象方法不能使用private final 和static来修饰,因为这些关键字都是和重写相违背的
模版设计模式
把通用的部分抽象出来做一个抽象的父类,子类继承父类并且补全抽象方法
接口
接口就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,在根据具体情况吧这些方法写出来,接口是为了定义行为规范
语法
interface 接口名{//属性,//方法}
- 接口默认的方法都是抽象的,没必要写abstract
class 类名 implements 接口{//自己的属性,//自己的方法,//必须实现接口的抽象方法 }
在jdk7以前,接口里所有方法都没有方法体,jdk8.0后接口可以有静态方法,默认方法(必须写default)
使用细节
接口不能被实例化
接口中所有方法是public方法,接口中抽象方法可以不用abstract来修饰
一个普通类实现接口,就必须将该接口的所有方法都实现,可以使用alt+enter 来解决
抽象类实现接口,可以不实现接口的方法
一个类可以实现多个方法
接口汇总的属性,只能是final的,而且是public static final, 比如int a = 1;实际上是public static final int a =1;(必须初始化)
接口汇总属性的访问形式:接口名.属性名
一个接口不能继承其他的类,但是可以继承多个别的接口
接口的修饰符只能是public和默认,和类是一样的(public class )
如果接口和继承的父类有同一个名称(x)属性的话,子类使用(x)必须要声明是哪个的
接口vs继承
继承是 is a 的关系,接口是has a 的关系
接口是一种规范,继承是一种减少代码量的模版
继承只能单继承,接口可以有多个
接口在一定程度上实现代码解耦【接口规范性+动态绑定机制】
接口的多态特性
接口同样可以有不同的“运行类型”“编译类型”
interface USB{ public void connect();}class MyUSB implements USB{ public void connect(){ System.out.println("USB connected"); }}class AnotherUSB extends MyUSB{ public void connect(){ System.out.println("Another USB connected"); }} MyUSB usb = new MyUSB(); usb = new AnotherUSB();
多态参数:一个接口可以接受多个实现了接口的类
interface USB{ public void connect();}class MyUSB implements USB{ public void connect(){ System.out.println("USB connected"); }}class MyPrinter implements USB{ public void connect(){ System.out.println("Printer connected"); }}class MyComputer{ private USB usb; public MyComputer(USB usb){ this.usb = usb; } public void connect(){ usb.connect(); }}
多态数组:同样可以用instance of来遍历数组,使用类特有的方法 接口的多态传递
interface USB{ public void connect();}interface usbFactory extends USB{
}
内部类
介绍
一个类的内部又完整的嵌套了另一个类就结构,被嵌套的类被称为内部类(inner class),嵌套其他类的类被称为外部类,是类的第五大成员(成员属性,成员方法,代码块,构造器,内部类),内部类最大的特点就是可以直接访问私有属性,并且可以提现类与类之间的包含关系
分类
-
定义在外部类局部位置上(比如方法内):
- 局部内部类(有类名)
- 匿名内部类(没有类名)
-
定义在外部类的成员位置上:
- 成员内部类(没有static修饰)
- 静态内部类(使用static修饰)
局部内部类
语法示例
class Outer02{public void m1(){ class Inner02{ }}}
细节与使用
局部内部类是定义在外部类的局部位置,比如方法中,并且有类名
可以直接访问外部类的所有成员,包括私有的
不能添加访问修饰符,因为它的地位就是一个局部变量,局部变量不能使用访问修饰符,但是可以使用final修饰,因为局部变量也可以使用final
作用域:仅仅在定义它的方法或代码块中
局部内部类——访问——外部类的成员【访问方式:直接访问】
外部类——访问——局部内部类的成员【访问方式:创建对象再访问,必须在作用域内】
外部其他类不能使用局部内部类,因为局部内部类地位是一个局部变量
如果外部类和局部内部类的成员重名时,遵循就近原则,如果想访问外部类的成员,可以使用外部类名.this.成员去访问
- 外部类名.this本质上是外部类的对象,即哪个对象调用了这行代码,外部类名.this就是哪个对象
匿名内部类
本质是类,内部类,该类没有名字,同时还是对象,继承了new 后面的对象
语法
new 类或接口(参数列表){类体};
示例
interface IA{ public void methodA();}public class Test { public static void main(String[] args) { IA obj = new IA() { @Override public void methodA() { System.out.println("Method A"); } }; obj.methodA(); }}
作用
用于只使用一次的类,简化开发
可以用来当做实参直接传递
本质
jdk底层在创建匿名内部类的时候,立即就创建了实例,并且把地址返回给对象的引用
细节
- 匿名内部类使用一次就不能再使用
- 可以访问外部类的所有成员,包括私有的
- 不能添加访问修饰符,因为它的地位就是一个局部变量
- 作用域:仅仅在定义它的方法或者代码块汇总
- 匿名内部类 直接访问 外部类成员
- 外部其他类 不能访问 匿名内部类(因为匿名内部类地位就是一个局部变量)
- 如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如果访问外部类的成员,则可以使用外部类名.this.成员去访问
成员内部类
成员内部类是定义在外部类的成员位置,并且没有static修饰
语法例子
class Outer{ public class Inner{
}}
细节
可以直接访问外部类的所有成员,包括私有的
可以添加任意访问修饰符,因为它的地位就是一个成员
作用域:和外部类的其他成员一样,为整个类体
成员内部类 访问 外部类(直接访问)
外部类 访问 内部类(创建对象,再访问)
外部其他类 访问 成员内部类(两种方式)
- 先创建外部类,然后创建内部类
- 在外部类中,编写一个方法,可以返回Inner对象
如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用外部类名.this.成员去访问
静态内部类
静态内部类是定义在外部类的成员位置,并且有static修饰
语法示例
class Outer{ public static class Inner{
//静态成员只能访问静态方法或者变量 }}
细节
可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员
可以添加任意访问修饰符,因为它就是一个成员
作用域:和其他成员相同,是整个类体
静态内部类 访问 外部类(直接访问)
外部类 访问 静态内部类(创建对象,在访问)
外部其他类 访问 静态内部类(两种方式)
- 创建对象后访问
- 写一个方法来访问
如果外部类和静态内部类的成员重名时,静态内部类访问的时候,遵循就近原则,如果想访问外部类的成员,可以使用外部类名.成员去访问
评论