1.类和对象
类与对象时整个面向对象中最基础的组成单元。
类:是抽象的概念集合,表示的是一个共性的产物,类之中定义的是属性和行为(方法);
对象:对象是一种个性的表示,表示一个独立的个体,每个对象拥有自己独立的属性,依靠属性来区分不同对象。
类与对象的区别:类是对象的模板,对象是类的实例。类只有通过对象才可以使用,而在开发之中应该先产生类,之后再产生对象。类不能直接使用,对象是可以直接使用的。
定义一个类的基本格式
[修饰符] class 类名{
0到多个构造器
0到多个成员变量
0到多个方法
0到多给初始化块
}修饰符可以写public final abstract或者不写,java类名要用大驼峰写法。一个java源文件(也就是文件后缀名为.java的文件)可以写多个类,但是里面只能有一个用public修饰的class,
final关键字
1.用来修饰一个引用
如果引用为基本数据类型,则该引用为常量,该值无法修改;
如果引用为引用数据类型,比如对象、数组,则该对象、数组本身可以修改,但指向该对象或数组的地址的引用不能修改。
如果引用时类的成员变量,则必须当场赋值,否则编译会报错。
2.用来修饰一个方法
当使用final修饰方法时,这个方法将成为最终方法,无法被子类重写。但是,该方法仍然可以被继承。
使用final方法的原因主要有两个:
(1)把方法锁定,以防止继承类对其进行更改。
(2)效率,在早期的java版本中,会将final方法转为内嵌调用。但若方法过于庞大,可能在性能上不会有多大提升。因此在最近版本中,不需要final方法进行这些优化了。
final方法意味着“最后的、最终的”含义,即此方法不能被重写。
注意:若父类中final方法的访问权限为private,将导致子类中不能直接继承该方法,因此,此时可以在子类中定义相同方法名的函数,此时不会与重写final的矛盾,而是在子类中重新地定义了新方法。
3.用来修饰一个类
当用final修饰类时,该类成为最终类,无法被继承,该类就不能被其他类所继承。当我们需要让一个类永远不被继承,此时就可以用final修饰,但要注意:
final类中所有的成员方法都会隐式的定义为final方法。
2.构造器
什么是构造器
构造器通常也叫构造方法、构造函数,构造器在每个项目中几乎无处不在。当你new一个对象时,就会调用构造器。构造器格式如下:
[修饰符,比如public] 类名 (参数列表,可以没有参数){ //这里不能有return}
构造器的注意事项:
1.构造器的名称必须和类名一致
2.一个类中可以定义多个构造器,但是构造器的参数列表必须不同(重载)
3.如果我们没有手动定义构造器,则Java系统会提供一个默认的构造器给我们使用,一旦我们定义了构造器,则系统会把默认的构造器收回
4.构造器的作用:实例化对象,给对象赋初始值
5.代码游离块优先执行
构造器的定义
构造方法的名字必须和所在类的名字一致,没有返回值,但不能声明void,访问权限可以为任意,但是一般情况下使用public方法权限,构造方法中的参数可以根据需要自行定义,参数的不同的构造方法构成重载
构造器的使用
Java中构造方法的使用有两个地方,一个是跟在关键字new后面,类名加上一个小括号(),小括号内根据实际加上实参,另外一个是跟在关键字super或this后加上一个小括号(),小括号内根据实际添加实参
构造器的继承
1)子类构造器会默认调用父类无参构造器,如果父类没有无参构造器,则必须在子类构造器的第一行通过 super关键字指定调用父类的哪个构造器
2)final类是不允许被继承的,编译器会报错。很好理解,由于final修饰符指的是不允许被修改,而继承中,子类是可以修改父类的,这里就产生冲突了,所以final类是不允许被继承的。
构造器、静态代码块、构造代码块的执行顺序
1.无继承的情况下的执行顺序静态代码块:只在程序启动后执行一次,优先级最高构造代码块:任何一个构造器被调用的时候,都会先执行构造代码块,优先级低于静态代码块构造器:优先级低于构造代码块总结一下优先级:静态代码块 > 构造代码块 > 构造器
2.有继承的情况下的执行顺序:父类静态代码块:只在程序启动后执行一次,优先级最高 子类静态代码块:只在程序启动后执行一次,优先级低于父类静态代码块 父类构造代码块:父类任何一个构造器被调用的时候,都会执行一次,优先级低于子类静态代码块父类构造器:优先级低于父类构造代码子类构造代码块:子类任何一个构造器被调用的时候,都会执行一次,优先级低于父类构造器子类构造器:优先级低于子类构造代码块总结一下优先级:父类静态代码块 > 子类静态代码块 > 父类构造代码块 > 父类构造器 > 子类构造代码块 > 子类构造器
3.成员变量和局部变量
Java 语言中若变量按声明的位置分类,可以分为:成员变量、局部变量,而成员变量又分为:实例变量,全局变量。实例变量是指不使用static修饰的变量,全局变量是指使用static修饰的变量。 局部变量包括:方法内声明的变量、方法的形参、构造器的形参、代码块内声明的变量。
相同点:
1.声明格式相同
格式: 数据类型 变量名 = 变量值
2.变量,必须先声明后使用
3.变量,都有其作用域
不同点:
1.声明的位置不同:
成员变量:直接声明在类的内部
局部变量:方法内声明的变量
方法的形参、构造器的形参
代码块内声明的变量。
2.权限修饰符的使用:
成员变量:可以在声明的类型前,指明权限修饰符。
权限修饰符有:private、public、protected、缺省
局部变量:不可以声明权限修饰符
3.默认初始化值:
成员变量:在声明时,如果没有显示赋值。则其有默认初始化值。
byte/short/int/long : 0
float/double : 0.0
char : 0 或 '\u0000'
boolean : false
引用类型: null
局部变量:在使用变量前,一定要进行显示初始化。即:局部变量没有初始化值
对于方法的形参(局部变量的一种)而言,是在调用方法时,给形参赋值。
4.在内存中加载的位置不同:
成员变量:声明在堆空间中
局部变量:声明在栈空间中
4.赋值过程
java的赋值语句是“=”号,比如把1赋值给a可以写:int a = 1;,如果是String类型可以写:String a = "1";,对象可以写成User u1 = new User();。
● 变量之间的赋值,可以说没有所谓的值赋值和地址赋值。
● 简而言之,将一个变量a赋值给另一个变量b,是将这个变量a的值,拷贝一份给变量b(如果a是引用类型,就拷贝引用,如果是基本类型,就拷贝原始值)
所赋的值
1.默认值
2.显示赋值
3.构造器赋值
4.对象名.属性名/对象名.方法名()
5.代码块赋值
{}
成员代码块/构造代码块
静态代码块
构造代码块/ 成员代码块:
位置: 类中方法外
作用: 给成员变量赋值
声明方式: {}
执行顺序: 先从上到下依次执行代码块 执行完毕再执行 构造器
一个类中可以存在多个代码块(先代码块后构造器)
注意:
创建几次对象 构造代码块就会执行几次
5.重载(Override)和重写(Overload)
1)重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。
即外壳不变,核心重写
2)重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。
3)重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。
例如: 父类的一个方法申明了一个检查异常 IOException,但是在重写这个方法的时候不能抛出 Exception 异常,因为 Exception 是 IOException 的父类,抛出 IOException 异常或者 IOException 的子类异常。
在面向对象原则里,重写意味着可以重写任何现有方法。
方法重写规则
-
参数列表与被重写方法的参数列表必须完全相同。
-
返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类(java5 及更早版本返回类型要一样,java7 及更高版本可以不同)。
-
访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected。
-
父类的成员方法只能被它的子类重写。
-
声明为 final 的方法不能被重写。
-
声明为 static 的方法不能被重写,但是能够被再次声明。
-
子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。
-
子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。
-
重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
-
构造方法不能被重写。
-
如果不能继承一个类,则不能重写该类的方法。
重载(Overload)
重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
最常用的地方就是构造器的重载。
重载规则
- 被重载的方法必须改变参数列表(参数个数或类型不一样);
- 被重载的方法可以改变返回类型;
- 被重载的方法可以改变访问修饰符;
- 被重载的方法可以声明新的或更广的检查异常;
- 方法能够在同一个类中或者在一个子类中被重载。
- 无法以返回值类型作为重载函数的区分标准。
方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。
- (1)方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)。
- (2)方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding)。
- (3)方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
6.内部类
内部类,就是在一个类中在定义一个类,包含内部类的类称为外部类。Java中一共有四种内部类:成员内部类,静态内部类,方法内部类,匿名内部类。内部类的意义是内部类和外部类可以方便访问彼此的私有域,内部类也是一种封装的表现,且内部类可以使用private关键字,内部类还能变相实现多继承。
注意:
- 内部类和外部类可以方便的互相访问彼此的private域。
- 内部类可以直接访问外部类的私有属性,但外部类要访问内部类的私有属性,必须创建内部类对象,再通过创建的内部类对象访问。
- 内部类是一个相对独立的个体,与外部类不是is a关系(人体和心脏)
1.成员内部类:
成员内部类:直接定义在类中不加任何修饰符(static)定义的类
成员内部类可以类比成员方法/属性,成员方法能访问静态域,不能拥有静态域。
注意
成员内部类必须依赖于外部类。
成员内部类能否定义一个静态变量?不能,成员内部类必须依赖于外部类,若成员内部类有静态属性,没有外部类也能访问。
成员内部类对象的创建有两种:
- 1.外部类的内部创建
和使用其他普通类没什么区别
- 2.外部类的外部创建
在外部类的外部创建内部类对象-内部类要对外部可见(访问权限问题)
2.静态内部类:
静态内部类:定义在类中,用static修饰的内部类
注意
与成员内部类的区别:静态内部类不需要依赖外部类对象!
静态内部类不可以使用任何外部类的非static类(包括属性和方法),但可以存在自己的成员变量。
静态内部类就是普通类,只是套在了类的内部而已
成员内部类可以访问外部类的成员域和静态域,但不能拥有静态域;静态内部类可以拥有成员域,但不能直接访问外部类的成员域,静态域,随便访问。静态方法能访问静态域不能访问成员域
创建静态内部类对象有两种方式
- 1.外部类的内部
- 2.外部类的外部
外部类.内部类 引用 = new 外部类.内部类();
3.方法内部类:
方法内部类: 直接定义在方法内部的类,不允许使用任何访问修饰符,对外部完全隐藏,出了方法就没有了。
注意:
- 方法内部类无法定义static域,除此之外和成员内部类的使用相同
- 方法内部类若使用了方法的形参,该形参为隐式的final声明
4.匿名内部类:
匿名内部类是方法内部类的特殊,不写类名称。
匿名内部类遵从方法内部类的所有要求
匿名内部类默认会继承一个类或实现一个接口。