面向对象总结(尚硅谷)
- 1.属性(成员变量)VS 局部变量
- 2.创建对象数组
- 3.面向对象思想三大主线
- 4.方法的重载
- 5.可变个数形参的使用
- 6.关于变量的赋值
- 7.内存结构
- 8.封装性的体现
- 9.四个权限修饰符
- 10.构造器
- 11.属性赋值的先后顺序
- 12 .this关键字
- 13.package关键字
- 14.import关键字
- 15.继承性
- 16. 方法的重写
- 17.super关键字
- 18.子类对象的实例化过程
- 19.多态性
- 20. instanceof 关键字
- 21.Object类
- 22. ==和 equals()的区别
- 23. 包装类
- 24. static关键字
- 25. 单例设计模式
- 26.代码块
- 27.final关键字
- 28.抽象类和抽象方法
- 29.接口
- 30. 内部类
1.属性(成员变量)VS 局部变量
相同点:
- 数据类型 变量名 = 变量值
- 先声明,后使用
- 变量都有对应的作用域
不同点:
-
在类中声明的位置不同:
- 属性:直接定义在类的{}中
- 局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量
-
关于权限修饰符的不同
常用的权限修饰符:public、private、缺省、protected
- 属性:可以在声明属性时,指明其权限,使用权限修饰符
- 局部变量:不可以使用权限修饰符
-
默认初始化情况
- 属性:类的属性,根据其数据类型,都有默认初始化值
- 整型(byte、short、int、long):0
- 浮点型(float、double):0.0
- 字符型(char):0(‘\u0000’)
- 布尔型(boolean):false
- 引用数据类型(类、接口、数组):null
- 没有默认初始值,意味着在调用局部变量之前,一定要显示赋值
- 属性:类的属性,根据其数据类型,都有默认初始化值
-
在内存中加载的位置
- 属性:加载在堆中(非static)
- 局部变量:加载在栈中
2.创建对象数组
两个步骤:
- 声明数组,此时每个元素都是null
Person[] per=new Person[20];
- 为元素赋值:
for(i=0;i<20;i++){Person per[i]=new Person }
3.面向对象思想三大主线
- 类及类的成员:属性、方法、构造器;代码块、内部类
- 三大特征:封装、继承、多态
- 其他关键字:this\super\abstract\interface\static\final\package\import…
4.方法的重载
- 定义:在一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数数据类型不同即可
- 举例:Arrays中的sort()、 binarSearch()
- 判断:两同两不同:
- 类和方法名相同
- 参数个数或者参数类型不同
- 与方法的权限修饰符、返回值类型、参数名、方法体都没有关系
- 如何判断调用的是哪一个方法:方法名----> 参数列表
5.可变个数形参的使用
- 格式:数据类型…变量名
- 当调用可变形参的方法时,传入的参数个数可以是0、1、2…
- 可变个数形参的方法与本类中方法名相同、形参不同的方法之间构成重载
- 可变个数形参的方法与本类中方法名相同,形参类型也相同的数组之间不构成重载,二者等价
- 可变个数形参在方法的形参中只能出现一个,且必须放在最后
6.关于变量的赋值
- 如果变量是基本数据类型,此时赋值的是变量所保存的数据值
- 如果变量是引用数据类型,此时赋值变量所保存的是数据的地址值
(注:引用数据类型有数组、类、接口,引用数据类型的变量只有两种值:null和包含类的地址)
7.内存结构
- 栈(stack):存储局部变量(方法内、方法形参、构造器内、构造器形参、代码块)
- 堆(heap):存储new出来的数据(对象、数组)
8.封装性的体现
- 将属性私有化(private),外部通过get/set方法对属性进行调用
- 仅供内部使用的方法
- 单例设计模式
- …
高内聚、低耦合
9.四个权限修饰符
- 从小到大排序:private、缺省、protected、public
- 四种权限修饰符都可以用来修饰类的内部结构:属性、方法、构造器、内部类
- 对于类来说,只能用缺省和public来修饰
- Java同过四种权限来对类及类的内部结构进行修饰,设置了其在被调用时的可见性
10.构造器
- 作用:
- 创建类的对象
- 初始化对象的信息
- 用法:
- 如果没有显示的定义一个类的构造器的话,则系统会提供一个默认的空参构造器,默认空参构造器的权限修饰符和类相同
- 定义构造器的格式:权限修饰符 类名(){}
- 一个类中出现的多个构造器也构成重载
- 一旦自己显示地定义了构造器之后,系统则不会提供构造器了
- 一个类中至少要有一个构造器
11.属性赋值的先后顺序
- 默认初始化
- 显示初始化 / 代码块中赋值,看谁声明的位置先就先赋谁
- 构造器赋值
- 通过 对象.方法 或者 对象.属性
12 .this关键字
this 可以使用在属性、方法、构造器上
在类的方法或者构造器中,我们可以使用this.属性 this.方法
的方式,调用当前对象(或者正在创建的对象)的属性或方法。但是通常情况下都选择省略this.
。特殊情况,如果方法或构造器中的形参和类的属性同名时,必须显式的使用this.
,标明此变量是属性而不是形参。
this调用构造器:
- 在类的构造器中,可以显式的使用
this(形参列表)
的方式,调用本类中指定的其他构造器 - 构造器中不能通过
this(形参列表)
的方式调用自己(死循环) - 如果一个类中有n个构造器,那么最多n-1个构造器用
this(形参列表)
来调用其他构造器 this(形参列表)
必须方法构造器的首行- 构造器内部最多只有一个
this(形参列表)
语句
13.package关键字
- 为了更好地实现项目的管理,提供包的概念
- 使用package声明类或接口所属的包,声明在源文件的首行
- 每"."一次,就是一层文件目录
补充:同一个包下,不能命名同名的接口、类
不同的包下,可以命名同名的接口、包
14.import关键字
- 在源文件中显式的导入指定包下的类或接口
- 声明在包的声明和类的声明之间
- 如果需要导入多个类或者接口,那么就并列显式多个import语句
- 可以使用 java.util.*的方式,一次性导入util包下的所有的类和接口
- 如果导入的类是java.lang包下的,或者是当前包下的,则可以省略此import语句
- 如果在代码中使用了不同包下的同名的类,那么就需要使用类的全类名的方式指明调用的是哪一个类
- 如果已经导入java.a包下的类,那么如果需要使用a包下的子包下的类的话,任然需要导入
import static 组合的使用,调用指定类或接口下的静态的属性或方法
15.继承性
1.继承性的好处:
- 减少了代码的冗余,提高了代码的复用性
- 便于功能的拓展
- 为之后多态性的使用,提供了前提
2.继承性的格式:class A extends B{}
A:子类、派生类、subclass
B:父类、超类、基类、superclass
- 体现:一旦子类继承了父类B以后,子类中就获取了父类B中声明的所有的属性和方法。特别的,父类中声明为private的属性和方法,子类继承父类之后,任然认为获取了父类的私有结构,只是因为封装性的影响,使得子类无法直接调用父类的私有结构
- 子类继承父类之后,还可以声明自己特有的属性或方法,实现功能的拓展。
3.java 中继承性的规定:
- 一个类可以被多个类继承
- java中的类的单继承性:一个类只能有一个父类
- 子父类是相对的概念
- 子类直接继承的父类称为直接父类,间接继承的父类称为间接父类
- 子类继承父类以后,就获取了直接父类以及所有间接父类中声明的属性和方法
4.关于object类
- 如果没有显式的声明一个类的父类的话,则此类继承于java.lang.Object类
- 所有的java类除了 java.lang.Object 类以外都继承于java.lang.Object类,意味着所有的类都可以调用Object类中的属性和方法。
16. 方法的重写
- 重写:子类继承父类以后,可以对父类中同名同参数列表的方法进行覆盖操作
- 应用:重写以后,当子类对象调用父类中被重写的方法是,实际执行的是子类中重写父类的方法
- 规定:
- 方法的声明: 权限修饰符 返回值类型 方法名(形参列表) throws 异常的类型{ }
- 子类重写的方法的方法名和参数列表应该和父类中被重写的方法的方法名和参数列表相同
- 子类重写的方法的权限修饰符不小于父类被重写的方法的权限修饰符(特殊情况,子类中不能重写父类中声明为private的方法)
- 返回值类型:
- 父类被重写的方法的返回值类型是void,则子类重写的方法返回值类型只能是void
- 父类被重写的方法是A类型,则子类重写的方法的返回值类型可以是A类型或者是A类型的子类
- 父类被重写的方法的返回值类型是基本数据类型,则子类重写的方法返回值类型只能是相同的基本数据类型
- 子类重写的方法抛出的异常不能大于父类中被重写方法抛出的异常
- 子类和父类中同名同参数的方法,要么都声明为非static的(构成重写),要么都是static的(不能构成重写)
区分重写和重载
17.super关键字
- super理解为:父类的
- super可以用来调用:属性、方法、构造器
- super的使用:调用属性和方法
- 我们在子类的方法或构造器中,通过使用
super.属性
或者super.方法
的方式,显示的调用父类中声明的属性或者方法。但是在通常情况下,我们习惯性省略super.
- 特殊情况,如果子父类中声明了同名的属性或者子类重写了父类的方法,并且想调用父类的属性或被重写的方法时,
super.
不能省略
- 我们在子类的方法或构造器中,通过使用
- 调用构造器
- 我们可以在子类的构造器中显式地使用
super(形参列表)
的方式,调用父类的构造器 super(形参列表)
的使用,必须在子类构造器的首行,所以在类的构造器中super(形参列表)
和this(形参列表)
只能二选一,因为两个都要求放在第一行- 在构造器的首行,如果没有显式的定义
super(形参列表)
和this(形参列表)
,则默认调用的是父类的空参构造super()
- 在类的多个构造器中(假设n个),因为最多n-1个调用
this
,所以至少有一个构造器调用了父类构造器
- 我们可以在子类的构造器中显式地使用
18.子类对象的实例化过程
-
从结果上看:(继承性)
- 子类继承父类以后,就获取了父类中声明的属性或方法
- 创建子类的对象,在堆空间中,就会加载所有父类中声明的属性
-
从过程上看:
当我们通过子类的构造器创建子类对象时,我们一定会直接或间接的调用其父类的构造器,进而调用其父类的父类的构造器…直到调用了java.lang.Object类的空参构造器为止。正因为加载过所有父类的结构,所以才可以看到内存中有父类中的结构,子类对象才可以考虑进行调用
-
需要明确的是,在创建子类对象时,虽然调用了父类的都构造器,但是自始至终都只创建了一个对象,即就是new 出来的子类对象
19.多态性
- 理解:一个事物的多种形态
- 形式:父类引用指向子类对象 (
父类 对象名=new 子类()
) - 使用:虚拟方法的调用。有了对象的多态性后,我们在编译期,只能调用父类中声明的方法;但是在运行期,实际执行的是子类重写父类的方法
- 总结:编译看左边;运行看右边
- 使用前提:①类的继承性②方法的重写
- 对象的多态性只适用于方法,不适用于属性(编译和运行都看左边)
多态性是运行时行为。
向下转型:
引入:有了对象的多态性以后,内存中实际是加载了子类特有的方法和属性的,但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的方法和属性。子类中特有的方法和属性不能调用。为解决这一问题,有了向下转型
class A extends B;
B b = new A();
A a = (A) b;
转型之后即可调用子类特有的方法。使用强转时,可能会出现类型转换异常
20. instanceof 关键字
- 使用:
a instanceof A
,判断对象a 是否是 类A 的实例,如果是,返回true,如果不是,返回false - 使用情境:为了避免在向下转型时出现类型转换异常,在向下转型之前,先进行instanceof 的判断,一旦返回true,就进行向下转型
- 注意:如果 a instanceof A 返回true ,则 a instance B 也返回true, 其中类B是类A的父类
21.Object类
- Object类是所有java类的父类
- 如果在类的声明中未使用extends关键字指明其父类,则默认父类为 java.lang.Object 类
- Object类中的功能具有通用性
- 属性:无
- 方法:equals()\ toString()\ getClass() \ hasCode() \ clone() \finalize() \wait() \notify() \notifyAll() \
- Object类中只声明了一个空参构造器
22. ==和 equals()的区别
==的使用:
- 可以使用在基本数据类型变量和引用数据类型变量中
- 如果比较的是基本数据类型:比较两个变量保存的数据是否相等。(不一定要类型相同的,因为有自动类型转换);如果比较的是引用数据类型变量:比较两个对象的地址值是否相同,即两个引用是否指向同一个对象实体
equals() 方法的使用:
- 是一个方法,而非运算符
- 只能适用于引用数据类型
- Object 类中equals 的定义与 == 的作用是相同的:比较两个对象的地址值是否相同
- 像 String \ Date \ File \ 包装类等都重写了Object 类中的 equals() 方法。重写以后,比较的不再是两个引用的地址值,而是比较两个对象的“实体内容”是否相同
- 通常情况,自定义的类使用equals() 的话,比较的也是实体内容,所以就需要对自定义类中的equals() 进行重写。有快捷键
toString() 方法的使用:
-
当输出一个对象的引用时,实际上就是调用当前对象的toString() 方法
-
Object 类中toString() 的定义
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
-
像String 、 Date、File、包装类等都重写了Object类中的toString()的方法,使得在调用对象的toString() 时,返回实体内容信息
-
自定义类也可以重写toString() 方法,调用此方法时,返回实体内容,有快捷键
23. 包装类
基本数据类型—>包装类:调用构造器
包装类转—>基本数据类型:*** value()
JDK 5.0以后的新特性:自动装箱和自动拆箱
**注意:Integer内部定义IntegerCache结构,IntegerCache中定义了Integer[],保存了从-128~127范围的整数。如果我们使用自动装箱的方式,给Integer赋值范围在<-128,127>时,可以直接使用数组元素而不用再去new
Integer i1=128;
Integer i2=128;
System.out.println(i1==i2);//false
Integer i3=128;
Integer i4=128; System.out.println(i3==i4);//true
24. static关键字
- static修饰的变量不归具体的对象所有,而是所有对象所共享的
- static可以修饰:属性、方法、代码块、内部类
static修饰属性
- 变量的分类
- 非静态变量(实例变量):没有static修饰,当我们实例化多个对象时,每个对象都独立拥有一套非静态变量,当修改其中一个对象的变量时,不会影响其他对象的变量
- 静态变量:有static修饰,当实例化多个对象时,多个对象共享一套静态变量,当修改一个变量的对象时,其他对象的变量也会随之改变。
- 调用静态变量时,可以通过类名访问;也可以通过对象访问。但通常都是用类名访问
- 静态变量的说明:
- 静态变量随着类的加载而加载;所以我们可以通过“类.变量”的方式调用
- 静态变量的加载早于对象的创建
- 由于类只会加载一次,则静态变量也只会在内存中存在一份,保存在方法区的静态域中
- 类可以调静态变量,不可以调实例变量;对象既可以调用静态变量,也可以调实例变量
static修饰方法
-
用static修饰的方法为静态方法
- 静态方法随着类的加载而加载,可以通过“类.静态方法”的方式调用
- 类可以调用静态方法,不可以调用非静态方法; 对象既可以调用静态方法,也可以调用非静态方法
- 方法间的调用:静态方法可以调用静态方法,但不能调用非静态方法; 非静态方法既可以调用静态方法,也可以调用非静态方法
-
static注意点
- 在静态的方法内,不能使用this和super关键子,因为这两个都是指代的某一个对象
- 对于静态方法和静态属性的使用,要参考生命周期
-
在开发中,如何确定一个属性是否要加static?
属性是多个对象所共有的,不会随着对象的不同而不同
-
如何确定方法是否要加static?
操作静态属性的方法通常加static
工具类中的方法 例如:Math、Arrays
25. 单例设计模式
- 所谓的单例设计模式,就是采取一定的方法,保证在整个软件系统中,对某个类只能产生一个对象实例。
- 实现:有懒汉式与饿汉式
- 懒汉式和饿汉式的对比:
- 饿汉式: 好处:线程安全 坏处:对象加载时间过长
- 懒汉式: 好处:延迟对象的创造 坏处:线程不安全
饿汉式:
//特点:事先给你创建好了对象
class Bank{
//私有化构造器,防止外部类创建对象
private Bank(){
}
//内部创建对象
private static Bank bank=new Bank();
public static Bank getinstance(){
//将对象返回给外部
return bank;
}
public void say(){
System.out.println("hello");
}
}
懒汉式:
//特点:比较懒,只有你请求的时候才会去创建对象
class Order{
//私有化构造器
private Order(){
}
//创建内部对象
private static Order instance=null;
//静态方法返回对象
public static Order getinstance(){
//线程不安全,判断完if后,还可能存在阻塞使其他线程进入从而创建两个对象
if (instance==null) {//如果不加if判断,则每一次调用的方法返回的都是不同的对象
instance=new Order();
}
return instance;
}
}
26.代码块
- 作用:用来初始化类、对象
- 代码块如果有修饰的话,只能使用static
- 分类:静态代码块 VS 非静态代码块
- 静态代码块:
- 内部可以有输出语句
- 随着类的加载而执行,而且只执行一次
- 作用:初始化类的信息
- 如果一个类中定义了多个静态代码块,则按照声明的先后顺序执行
- 静态代码块的执行要优先于非静态代码块
- 只能调用静态的属性和方法
- 非静态代码块
- 内部可以有输出语句
- 随着对象的创建而执行,而且每创建一次就执行一次
- 作用:初始化对象的信息
- 如果一个类中定义了多个非静态代码块,则按照声明的先后顺序执行
- 静态和非静态的属性和方法都可以调用
27.final关键字
- 可以用来修饰的结构:类、属性、方法
- final用来修饰一个类:此类不能被其他类继承。例如:String 类、StringBuffer 类、System类
- final 用来修饰一个方法,此方法不能被重写
- final用来修饰变量,此时的“变量”就称为是一个常量
- final修饰属性时:可以考虑赋值的位置有:显示初始化、代码块中的初始化、构造器中的初始化
- fianl修饰局部变量:尤其是fianl修饰形参时,表明此形参是一个常量。我们调用此方法时,给常量赋一个实参,一旦赋值以后,就只能在方法体内使用此形参、但不能对其进行重新赋值
28.抽象类和抽象方法
- 关键字:abstract
- abstract 可以用来修饰的结构:类、方法
- abstract 修饰类:抽象类
- 此类不能实例化
- 抽象类中一定有构造器,便于子类对象的实例化
- 开发中,都会体统抽象类的子类;让子类对象实例化,完成相关的操作
- abstract 修饰方法:抽象方法
- 抽象方法只包含方法的声明,不包含方法体
- 包含抽象方法的类一定是抽象类;反之。抽象类中可以没有抽象方法
- 若子类重写了父类的所有抽象方法,此子类可以实例化
- 若子类没有重写类的所有抽象方法,则此子类也需要是一个抽象类
- 使用上的注意点:
- abstract 不能用来修饰属性、构造器
- abstract 不能用来修饰私有方法、静态方法final的方法、final的类
29.接口
- 接口用interface来定义
- Java中,类和接口是并列的两个结构
- 如何定义接口:定义接口中的成员
- JDK7及以前,只能定义全局常量和抽象方法
- 全局常量:
public static final
的,但是书写时,可以省略不写 - 抽象方法:
public abstract
- JDK8:除了定义全局常量和抽象方法以外,还可以定义静态方法、默认方法
default 类型 方法名()
- 接口中定义的静态方法,只能通过接口来调
- 通过实现类的对象,可以调用接口中的默认方法,调用时认识调用重写后的方法
- 如果子类(实现类)继承的父类和实现的接口中声明了同名同参数的默认方法,那么在子类没有重写此方法的情况下,默认调用的是父类中的方法。如果声明了同名的属性则会报错
- 如果实现类实现了多个接口,而这多个接口中定义了同名同参数的默认方法,那么在实现类没有重写此方法的情况下,会报错–》接口冲突
- 如何在子类(实现类)中调用父类(接口)中被重写的方法
super.method() 接口名.super.method()
- 接口中不能定义构造器,这意味着接口不能被实例化
- Java开发中,接口通过让类去实现(implements)的方式来使用;如果实现类实现了接口中所有的抽象方法,则此实现类就可以实例化;如果实现类没有实现接口中的所有抽象方法,则此实现类就就是一个抽象类
- Java类可以实现多个接口—>弥补了单继承的局限性:格式
class AA extends BB implements CC,DD
- 接口与接口之间可以继承,而且可以多继承
- 接口的具体使用体现多态性
- 接口,实际上可以看做是一种规范
30. 内部类
-
Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B就是外部类
-
内部类的分类
- 成员内部类(静态、非静态)
- 局部内部类(方法内、代码块内、构造器内)
-
成员内部类:
- 作为外部类的成员:
- 调用外部的结构
- 可以被static修饰
- 可以被四种权限修饰符修饰
- 作为一个类:
- 类可以定义属性、方法、构造器
- 可以被final修饰,表示此类不可以被继承
- 可以被abstract修饰
- 作为外部类的成员:
-
重点:
-
如何实例化成员内部类的对象
public class Person { public static void main(String[] args) { Person.Dog dog=new Person.Dog(); Person.Cat cat=new Person().new Cat(); } static class Dog{//静态内部类 } class Cat{//非静态内部类 } }
-
如何在成员内部类中区分外部类的结构
public class Person { String name; class A{ String name; public void show(){ this.name="";//内部类中的 Person.this.name="";//外部类的 } } }
-
开发中局部内部类的使用:一般在方法中返回某个类的对象,或者实现了某个接口的类的对象
-