3种类型(类、接口、枚举)
4个修饰符(private | protected | public 、final、static、abstract)
5个成员(成员变量、构造器、方法、内部类、初始化块)
一、三种类型
1、类
-
类:是一组相关属性和行为的集合。可以看成是一类事物的模板,使用事物的属性特征和行为特征来描述该类事物。
-
对象:是一类事物的具体体现。对象是类的一个实例,具备该类事物的属性和行为。
-
类与对象的关系
类是对一类事物的描述,是抽象的。
对象是一类事物的实例,是具体的。
类是对象的模板,对象是类的实体。[修饰符] class 类名{ //成员变量 //构造器 //成员方法 //内部类 //初始化块 }
修饰符:public、final | abstract
2、接口
(1)接口的定义
接口的定义,它与定义类方式相似,但是使用 interface 关键字。它也会被编译成.class文件,但一定要明确它并不是类,而是另外一种引用数据类型。
接口体现的是一种规范-----要暴露出来供大家遵守,所以接口里的东西都要用public修饰,不管写不写,始终有public修饰,通常都不写。
public interface 接口名{
//成员变量
//抽象方法(JDK 7及以前)、默认方法和静态方法(JDK 8)、私有方法(JDK 9)
//内部类
}
-
成员变量:只能是常量,默认有static final 修饰,可以省略。
-
抽象方法:使用abstract 修饰,可以省略,没有方法体。该方法供子类实现使用。
-
默认方法(相当于类的实例方法):使用default 修饰,不可省略,有方法体,供子类继承或者子类重写。
-
静态方法(相当于类的类方法):使用static 修饰,不可省略有方法体,使用接口名调用。
-
私有方法:使用 private 修饰。如果一个接口中有多个默认方法,并且方法中有重复的内容,那么可以抽取出来,封装到私有方法中,供默认方法或者静态方法去调用。从设计的角度讲,私有的方法是对默认方法和静态方法的辅助。
(2)接口的使用
接口的使用,它不能创建对象,但是可以被实现( implements ,类似于被继承)。一个实现接口的类(可以看做是接口的子类,是一个类),需要实现接口中所有的抽象方法,创建该类对象,就可以调用方法了,否则它必须是一个抽象类。
[修饰符] class 类名 implements 接口1,接口2···{ //重写接口中的所有抽象方法(必须) //默认方法同类中实例方法的继承(可重写可继承) }
(3)接口的多继承
一个类能继承一个父类,同时实现多个接口。
[修饰符] class 类名 (extends 父类名)implements 接口1,接口2···{ //5大成员 }
-
接口中,有多个抽象方法时,实现类必须重写所有抽象方法。如果抽象方法有重名的,只需要重写一次。
-
接口中,有多个默认方法时,实现类都可继承使用。如果默认方法有重名的,必须重写一次。
-
接口中,存在同名的静态方法并不会冲突,原因是只能通过各自接口名访问静态方法。
-
当一个类,既继承一个父类,又实现若干个接口时,父类中的成员方法与接口中的默认方法重名,子类就近选择执行父类的成员方法。
3、枚举
待补充
二、四个修饰符
1、public | protected | private
-
private(类访问权限):该修饰符修饰的成员,只能在该类中被访问。------彻底的隐藏
-
default或者不写(包访问权限):该修饰符修饰的成员,只能在该类及该类所在包中被访问。-----部分隐藏
-
protected(子类访问权限):该修饰符修饰的成员,只能在该类、及其该类所在的包、该类的子类中被访问。-----部分暴露
-
public(公共):该修饰符修饰的成员,可以在任意地方被访问。------彻底暴露
· private default或者不写 protected public 类 √ √ √ √ 同一包中的子类或者无关类 × √ √ √ 不同包中的子类 × × √ √ 任意 × × × √
2、final
final: 用于修饰不可改变内容。可以用于修饰类、方法和变量。
final与abstract互斥:永远不能同时出现。
- 类:被修饰的类,不能被继承。
- 方法:被修饰的方法,不能被重写。
- 变量:被修饰的变量,必须被赋值,且只能赋值一次。
特别的,引用类型的局部变量,被final修饰后,只能指向一个对象,地址不能再更改。但是不影响对象内部的成员变量值的
修改。
3、abstract
abstract:可以用于修饰类和方法。
final和abstract互斥:永远不能同时出现。
- 抽象方法 : 使用abstract 关键字修饰方法,该方法就成了抽象方法,抽象方法只包含一个方法名,而没有方法体。。
- 抽象类:包含抽象方法的类一定是抽象类。
1、抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
2、 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
理解:子类的构造方法中,有默认的super(),需要访问父类构造方法。
3、抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
4、 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。
区别接口和抽象类:
相同点:
(1)都不能被实例化(不能new对象)。
(2)接口的实现类或抽象类的子类都只有实现了接口或抽象类中的方法后才能实例化。
(3)抽象方法只有方法签名,没有方法体。不同点: (1)接口只有定义,不能有方法的实现,java
1.8后可以定义实现静态方法、默认方法、私有方法,而抽象类可以有定义与实现,方法可在抽象类中实现。
(2)实现接口的关键字为implements,继承抽象类的关键字为extends。一个类可以实现多个接口,但一个类只能继承一个抽象类。所以,使用接口可以间接地实现多重继承。
(3)接口强调特定功能的实现,而抽象类强调所属关系。
(4)接口成员变量默认为public static final,必须赋初值,不能被修改;其所有的成员方法都是public、abstract的。抽象类中成员变量默认default,可在子类中被重新定义,也可被重新赋值;抽象方法被abstract修饰,不能被private、static、synchronized和native等修饰,必须以分号结尾,不带花括号。
(5)接口被用于常用的功能,便于日后维护和添加删除,而抽象类更倾向于充当公共类的角色,不适用于日后重新对立面的代码修改。功能需要累积时用抽象类,不需要累积时用接口。
4、static
static可以修饰:成员变量、初始化块、方法、内部类
static是类的意思,有static的成员属于类成员,没有static修饰的成员属于实例成员。
static 修饰的内容:
- 是随着类的加载而加载的,且只加载一次。
- 存储于一块固定的内存区域(静态区),所以,可以直接被类名调用。
- 它优先于对象存在,所以,可以被所有对象共享。
static成员不能访问非static成员
非static成员可以访问static成员
三、5大成员
1、成员变量(field)
[修饰符] 类型 变量名 [= 初始值];
类变量(有static):类变量属于类本身,当系统初始化类时,就会为类分别分配空间,并执行初始化。
实例变量(没有static):实例变量属于对象本身,系统每次创建对象时,都需要为该对象的实例变量分配空间,并执行初始化。
2、构造器(constructor)
[修饰符] 构造器名(形参列表){
//代码:定义变量(包括数组)、变量赋值、流程控制、数据语句
}
修饰符:public|protected|private
- 如果你不提供构造方法,系统会给出无参数构造方法。
如果你提供了构造方法,系统将不再提供无参数构造方法。 - 构造方法是可以重载的,既可以定义参数,也可以不定义参数。
- 构造器如何调用?必须用new来调用构造器,这样可以返回一个初始化完成的对象。
- this调用:
this(参数);
可以调用类中重载的构造器,只能放在构造器的第一行。
3、方法(method)
[修饰符] 返回值类型 方法名(形参列表){
//代码:定义变量(包括数组)、变量赋值、流程控制、数据语句
//如果声明了返回值类型必须有return语句
}
修饰符:public|protected|private、static、final
(1)方法的所属性
- 定义在类中的方法。从逻辑上看,如果该方法有static修饰,该方法属于类本身,应该用类调用。如果该方法无static修饰,该方法属于对象本身。
方法不能独立执行。 - 方法一定要有调用者。如果调用同一个类中的方法,可以省略调用者,此时系统会添加默认的调用者。如果该方法是无static的方法,添加this作为默认的调用者。如果该方法是有static的方法,添加类名作为默认的调用者。
super :代表父类的存储空间标识(可以理解为父亲的引用)。
this :代表当前对象的引用(谁调用就代表谁)。
super和this的用法:
- 访问成员
this.成员变量 ‐‐ 本类的
super.成员变量 ‐‐ 父类的
this.成员方法名() ‐‐ 本类的
super.成员方法名() ‐‐ 父类的
- 访问构造器
this(...) ‐‐ 本类的构造方法
super(...) ‐‐ 父类的构造方法
子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super()。
super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现。
(2)形参可变的方法
类型[] 形参名
类型… 形参名
写法的好处是:调用方法时更加方便。既可以直接传入多个元素,系统会自动将它们封装成数组,也可用数组。
缺点是:这种写法只能作为形参列表的最后一个形参。(一个方法中最多只能有一个“个数可变的形参”)
(3)递归方法
(4)方法重载
口诀:两同一不同。
修饰符相同,返回值类型相同,形参列表不同。
(5)方法的传参机制
Java的传参机制:值传递,传入的只是参数副本,并不是参数本身。
如果传递的参数是基本类型,方法中对参数所做的修改完全不会影响参数本身。
如果传递参数是引用类型,参数的副本与参数指向同一对象。
因此此方法通过参数副本修改参数时,会影响参数本身所指向的对象。
4、初始化块
[static] {
//各种语句
}
有static叫类初始化块(静态初始化块)
无static叫实例初始化块(非静态初始化块)
(1)实例初始化块
实力初始化块是“假象”,一个类在编译过后,实例初始化块就会消失------实例初始化块的代码会被还原每个构造器的所有代码之前。
定义实例变量时指定的初始值也是“假象”-----指定初始值,编译之后就变成了每个构造器所有代码之前的一条赋值语句。
实例初始化块的语句要还原到构造器所有代码之前,定义变量指定的的初始值也要还原到构造器的所有代码之前:这二者还原之后的顺序按照它们在源代码中顺序。
(2)类初始化块
类初始化块----负责对类执行初始化,当程序第一次【主动】使用该类时,系统会为该类分配内存空间、并执行初始化(调用类初始化块)。
定义类变量时指定的初始值也是“假象”-----指定初始值,编译之后就变成了类初始化块中的一条赋值语句。但到底在类初始化的代码之前还是代码之后,取决于它在源代码中的顺序。
执行次数 | 执行先后 | 何时执行 | |
---|---|---|---|
类初始化块 | 1次 | 先 | 第一次主动调用该类 |
实例初始化块 | N次 | 后 | 每次调用构造器 |
5、内部类(nested class)
(1)成员内部类
成员内部类是最普通的内部类,它的定义为位于另一个类的内部。
成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。
- 当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:
外部类.this.成员变量;
外部类.this.成员方法;
- 在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问:
Outter outter = new Outter();
Outter.Inner inner = outter.new Inner();
内部类可以拥有 private 访问权限、protected 访问权限、public 访问权限及包访问权限。如果成员内部类 用 private 修饰,则只能在外部类的内部访问;如果是默认访问权限,则只能在同一个包下访问;如果用 protected 修饰,则只能在同一个包下或者继承外部类的情况下访问;如果用 public 修饰,则任何地方都能访问。
外部类只能被 public 和包访问两种权限修饰。
(2)局部内部类
局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。
局部内部类就像是方法里面的一个局部变量一样,是不能有 public、protected、private 以及 static 修饰符的。
(3)匿名内部类
待补充
(4)静态内部类
静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法,这点很好理解,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象。