Java-面向对象-05
1.1、面向过程 & 面向对象
-
面向过程思维:
- 步骤清晰简单,第一步做什么,第二部做什么...
- 面对过程适合处理一些较为简单的问题
-
面向对象思维:
- 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。
- 面向对象适合处理复杂的问题,适合处理需要多人协作的问题!
- 面向对象:从宏观的角度思考解决的过程。
- 对象的属性:每个对象的每个 属性 都拥有特定的 值。
- 对象的行为:对象能够 执行 的操作。
- 面向对象的三大特征:封装、继承、多态。
-
对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。
-
面向对象的本质就是:以类的方式组织代码,以对象的组织(封装)数据。
-
三大特性:
- 封装
- 继承
- 多态
1.2、类与对象的创建
-
类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物。
- 是对现实生活中一类具有 共同属性 和 行为 的事务的抽象。
- 如:动物、植物、手机、电脑...
-
对象是抽象概念的具体实例
- 能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念。
-
标准类制作:
- 成员变量
- 使用 private 修饰。
- 构造方法
- 提供一个 无参 构造方法。
- 提供一个带 多个参数 的构造方法。
- 成员方法
- 提供每一个 成员变量 对应的 set变量名() / get变量名()。
- 提供一个 显示 对象信息的 show()。
- 创建对象并为其成员变量赋值的两种方式
- 无参 构造方法创建对象后使用 set变量名() 赋值。
- 使用 带有属性 的构造方法直接创建带有属性值的对象。
- 成员变量
-
语法:
// 类的创建 public class 类名 { // 类属性:字段 String name; int age; // 类方法 public void study(){ System.out.println(this.name+"在学习"); } } // 类的调用 public class aaa { public static void main(String[] args) { 类名 对象名 = new 类名(); 对象名.方法名(或变量名); } }- 类的内容:
- 静态的属性 属性
- 动态的行为 方法
- 类的内容:
-
创建与初始化对象
-
使用 new 关键字创建对象
- 使用 new 关键字创建的时候,除了分配内存空间之外,还会给 创建好的对象 进行默认的初始化以及对类中构造器的调用。
-
语法:
// new 实例化对象 public static void main(String[] args) { // 类实例化后会返回一个自己的对象 类名 student = new 类名(); // 类属性赋值和调用 student.name = "123"; System.out.println(student.name); // 类方法调用 student.study(); } -
注意:
- 如果两个对象的地址一样,那么修改一个另一个跟着改变。
- 对象之前被 new ,那么再 new 一次的时候会创建一个新的对象堆内存。
-
1.3、构造方法
-
类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。
- 创建了构造方法,系统将不再提供默认的无参构造方法。
- 构造方法名称必须和 类名 一致。
- 要通过 new 关键字调用
- 构造器虽然有返回值,但是不能使用 return 返回某个值。
- 构造方法不需要数据类型。
-
构造器作用:
- 实例化初始值。
- 使用 new 关键字,本质是在调用构造器。
-
注意点:
- 定义有参构造之后,如果想使用无参构造,必须显示的定义一个无参的构造
-
语法:
public class Student { // 类属性 int age; // 无参构造器 public Student(){ this.age = 1; } // 有参构造:一旦定义了有参构造,无参就必须显示定义。 public Student(int age){ this.age = 1; } }-
构造方法的重载
- 方法名称相同,形参列表不同
-
注意:
- 无论是否使用,都手工书写无参构造方法。
- 垃圾回收机
-
1.4、封装
-
封装
- 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。
-
封装的优点:
- 提高代码的安全性。
- 提高代码的复用性。
- “高内聚” :封装细节,便于修改内部代码,提高可维护性。
- “低耦合” :简化外部调用,便于调用者使用,便于扩展和协作。
-
属性私有:
private:私有化属性或方法。
-
get、set 方法
- get:获得这个数据
- set:给这个数据设置值
-
访问权限修饰符
修饰符 同一个类 同一个包中 子类 所有类(不同包下的类) private * default(默认) * * protected * * * public * * * * -
语法:
// 操作类 public class Student { private String name; public String getName(){ return this.name; } public void setName(String name){ this.name = name; } } // 实例类 public static void main(String[] args) { Student student = new Student(); // 给这个数据设置值 student.setName("aa"); // 获得这个数据 System.out.println(student.getName()); } -
关键字
-
private:
- 被 private 修饰的变量(或 方法)只能在 本类 当中使用。
- 如果想被其它类使用需要使用方法:
-
get方法:
- 格式:
public 数据类型 get变量名() { return 变量名; }。 - 作用:用于获取值。
- 格式:
-
set 方法:
- 格式:
public void set变量名(参数) { 变量名 = 参数; }。 - 作用:用于设置值。
- 格式:
-
注意 :
- 子类 无法 使用父类的 私有 属性和方法。
- 被 private 修饰的方法可以使用
get变量名()来调用。
-
-
this:
- this 修饰的变量表示 成员变量。
- 方法的形参和成员变量名称 相同,带 this 的是 成员变量。
- 局部变量和成员变量名称相同 时,this 能解决局部变量隐藏成员变量。
- this 被那个对象引用那么它就代表那个对象。
- 格式:
- 成员变量:
this.成员变量- 构造方法:
this([实参]) - 成员变量:
this.成员方法([实参])
- 构造方法:
- this 修饰的变量表示 成员变量。
-
1.5、继承
-
继承的本质是对某一批类的抽象。
-
extands的意思是 “扩展”。子类是父类的扩展。 -
Java 中类只有单继承,没有多继承。
-
在 Java 中,所有的类,都默认直接或者间接继承 Object 类。
-
子类可以继承没有被
private修饰的变量或者方法。 -
在子类的构造器中不能同时使用
super和this关键字。 -
如果父类没有无参构造方法,子类无法使用构造方法。
- 可以在子类的构造方法中添加
super(实参);来使用子类的构造方法。
- 可以在子类的构造方法中添加
-
继承的变量访问范围:
- 子类 局部 范围找
- 子类 成员范围找
- 父类 成员范围找
- 如果都没有,则 报错。
-
super注意点:- super 调用父类的构造方法,必须在构造方法的第一个
- super 必须只能出现在子类的方法或者构造方法中
- super 和 this 不能同时调用构造方法
- 用来访问 父类 的成员变量和方法(创建父类成员变量或方法的存储空间)。
- 格式:
- 成员变量:
super.成员变量 - 构造方法:
super([实参]) - 成员方法:
super.成员方法([实参])
- 成员变量:
-
super和this的不同- 代表对象不同:
this:本身调用者这个对象。super:代表父类对象的应用。
- 前提:
this:没有继承也可以使用。super:只能在继承条件才可以使用。
- 构造方法:
this():本类的构造super():父类的构造
- 代表对象不同:
-
语法:
// 创建子类继承父类 public class 子类名 extends 父类名{ String name; public void print(){ } public void test(){ // 访问当前类中的变量或方法 this.name; this.print(); // 访问父类的变量或方法 super.name; super.print(); } }
-
继承中构造方法的特点:
- 子类中所有的构造方法 默认访问 父类中的 无参 的构造方法。
- 如果访问父类的 有参 构造方法,则需要在子类中添加
super(参数)。
-
继承中的成员方法
- 寻找范围:
- 子类成员范围找
- 父类成员范围找
- 如果都没有,则报错。
- 如果在子类中添加 super();,则会先运行父类再运行子类。( super(); 一般在子类的第一行)
- 寻找范围:
-
方法的重写
- 概述:
- 子类中出现了和父类 一样 的方法。
- 使子类沿袭父类的功能,又定义 了新的内容。
- 使用:
- 在方法重写的时候应在方法的上面使用
@Override进行注解,防止 方法重写错误。
- 在方法重写的时候应在方法的上面使用
- 注意事项:
- 父类的私有属性子类不可以重写。
- 子类的访问权限不能低于父类的访问权限。(public > 默认的 > 私有的)
- 概述:
-
继承的注意事项:
- 继承只支持单继承,不支持多继承。
- 继承支持多层继承类。
- 可以 new 子类,因为子类方法最多。
- 继承只支持单继承,不支持多继承。
1.6、修饰符
- 修饰符:范围可以扩大,但不能缩小。
- public:公共的
- private:私有的
- protected:受保护的
- default:默认的(不用写)
1.7、方法的重写
-
@Overide:表示重写 -
静态的方法重写:方法的调用只和左边,定义的数据类型有关,和重写无关。
-
非静态的方法才是重写。
-
重写:需要有继承关系,子类重写父类的方法。
- 方法名必须相同
- 参数列表必须相同
- 抛出的异常:范围可以被缩小,但不能扩大。
-
语法:
// 父类 public class Dome03 { public void test(){ } } // 子类 public class Dome02 extends Dome03{ public void test(){ } }
包管理
-
包
-
包的概述和使用:
- 作用:对类进行分类管理。
-
创建包管理格式:
package 包名; // 多级包用 . 分隔 -
new 不同包的类:
// 包名就是包的相对路径,文件之间使用 . 分隔 包名.类名 对象名 = new 包名.类名();
-
-
导包
-
概述:
- 使用包下类时,要写下类的路径,为了简化此操作,java提供了导包功能。
-
导包格式:
import 包的相对路径;
-
-
修饰符
- 权限修饰符
- 权限修饰符图在此 封装 链接中
- final 修饰符
- final 修饰基本类型,基本类型 重新赋值 报错。
- final 修饰引用类型,引用类型 改变地址值 则报错。
- static 修饰符
- 特点:
- static 关键字是静态的意思,可以 修饰 成员变量和成员方法。
- 被 static 修饰的可以被类的所有对象 共享。
- 可以通过类名或对象名 调用。
- 特点:
- 调用 static 修饰的成员变量(成员方法)格式:
- 成员变量:
类名.成员变量 = 元素; - 成员方法:
类名.成员方法([参数]);
- 成员变量:
- 注意事项:
- 静态的成员方法只能访问 静态的成员方法和成员变量。
- 权限修饰符
1.8、多态
-
一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多(父类,有关系的类)
new 类名()
-
可以指向的引用类型就不确定了:父类的引用指向子类
-
子类能调用的方法都是自己的或者继承父类的
-
父类型,可以指向子类,但是不能调用子类独有的方法
-
对象能执行那些方法,主要看对象左边的父类有哪些方法,和右边关系不大。
-
语法:
父类名 对象名 = new 子类名(); -
多态注意事项:
- 多态是方法的多态,属性没有多态
- 父类和子类,得有联系。
- 如果强制转换报:类型转换异常!(ClassCastException!)
- 存在条件:
- 有继承/实现关系。
- 有方法重写。
- 用父类引用指向(new)子类对象。
- 父类引用执行子类对象
- 被以下修饰的方法无法被重写
static方法:属于类,它不属于实例final:常量;private:方法:私有的方法无法被重写。
- 多态的成员访问特点
- 成员变量:编译看左边,执行看左边。
- 成员方法:编译看左边,执行看右边( 这里的 执行看右边 指的是继承中的方法的重写)
-
多态的好处和弊端:
-
创建一个类(第三类),在类里面定义一个方法,使用父类作为参数,将来使用的时候直接 new 第三类,再 new 子类,然后使用方法调用实参是子类。
-
创建多态:
// 父类中的方法 public void 方法名1(){ 方法体; } // 第三类中的方法 public void 方法名(父类 参数){ 参数.父类中的方法名(); } // 子类中的方法 @Override public void 方法名1(){ 方法体; } -
调用多态:
第三类 对象名1 = new 第三类(); 子类 对象名2 = new 子类(); 对象名1.第三类中的方法(对象名2);
-
-
多态 提高 了代码的扩展性。
-
多态 不能 直接访问子类特有的功能。
-
-
多态的转型
-
概述
- 帮助我们使用子类的特有功能。
-
类型:
-
向上转型
- 从子到父
- 父类引用指向子类对象
-
向下转型
- 从父到子
- 父类引用转为子类对象
-
格式:
//向上转型 父类 对象名1 = new 子类(); //向下转型 子类 对象名2 =(子类)对象名1;
-
- 注意:
- 向下转型的时候注意 对象名 的地址。
- 子类不能转换成子类。
-
1.9、instanceof 和类型转换
1.9.1、instanceof 关键字
-
instanceof:可以判断两个类之间是否是父子关系。- 是父子关系返回:
true - 不是父子关系返回:
false
- 是父子关系返回:
-
语法:
Object o = new String(); System.out.println(o instanceof String);
1.9.2、类型转换
-
子类往父类转,向上转型:自动转换
-
子类转换为父类,可能丢失一些自己本来的方法。
-
语法:
子类名 对象名1 = new 子类名(); 父类名 对象名2 = 对象名1;
-
-
父类往子类转,向下转型,需要强制转换
-
语法:
父类名 对象名1 = new 子类名(); 子类名 对象名2 = (子类名)对象名1;
-
-
父类引用使用子类独有的方法:
-
语法:
父类名 对象名 = new 子类名(); ((子类名)对象名).方法名();
-
1.10、static 关键字
- 被
static修饰的变量,建议使用类名.变量名调用。 - 被
static修饰的方法,建议使用类名.方法名();调用。 - 使用
static修饰导包语句,可以导入包里面的方法。import static java.lang.Math.random;
- 代码块:
-
语法:
{ /* 匿名代码块 */} static { /* 静态代码块 */ } -
匿名代码块:
- 一般用来赋初始值。
- 类不会主动执行
- 调用时需要使用 new 这个匿名代码块的类名。
-
匿名代码块:
- 类在加载时主动执行,且只执行一次。
-
1.11、抽象类
-
被
abstract关键字修饰的类,就是抽象类 -
被
abstract关键字修饰的方法,就是抽象方法- 抽象类中可以写普通的方法
- 抽象方法必须在抽象类中
-
抽象类的所有抽象方法,继承了它的子类,都必须要实现它的方法,除非子类也是抽象类。
-
抽象类不能 new,只能靠子类去实现它:约束!
-
语法:
// 抽象类 public abstract class 抽象类名 { // 抽象方法 public abstract void 抽象方法名(); } // 子类实现抽象类 public class 子类名 extends 抽象类名 { public void 抽象方法名(){ } }
-
抽象类
-
特定
- 要使用抽象方法,类 必须是抽象类。
- 抽象方法不能直接 new ,可以通过多态来实例化。
- 抽象类的子类要么 重写 抽象类的 所有 抽象方法,要么 设置 为抽象类。
-
定义格式:
// 创建抽象类 public abstract class 抽象类名{ // abstract 设置抽象类 public abstract void 方法名(); } //创建多态 public class 子类 extends 抽象类名{ public void 方法名(){ // 抽象方法的重写 方法体; } } // 调用 抽象类名 对象名 = new 子类(); // 通过多态调用 -
抽象类的成员特点
- 可以使用成员变量。
- 可以使用构造方法
- 有构造方法,但是不能调用。(就是不能被 new)
- 构造方法作用是:用于子类访问父类的数据的初始化,如:成员变量。
- 成员方法
- 可以有抽象方法,也可以没有。
- 限定子类必须完成某些动作。
-
1.12、接口
-
普通类:只有具体实现
-
抽象类:具体实现和规范(抽象方法)都有
-
接口:只有规范!自己无法写方法专业的约束
- 约束和实现分离:面向接口编程~
-
接口的作用:
- 约束
- 定义一些方法,让不同的人实现
- 接口中的方法和属性默认的修饰符:
- 方法的默认修饰符:
public abstract - 属性默认的修饰符:
public static final
- 方法的默认修饰符:
- 接口不能被实例化,接口中没有构造方法
implements可以实现多个接口- 实现接口,必须重写接口中的方法
-
声明类的关键字是 class,声明接口的关键字是 interface。
public interface 接口名 { }
-
子类实现接口:
public class 子类名 implements 接口名- 实现了接口的类,就需要重写接口中的方法
- Java 可以通过接口实现多继承
-
语法:
// 接口 public interface 接口名1 { void 方法名(); } // 子类实现接口 public class 子类名 implements 接口名1,接口名2 { @Override public void 方法名() { } }
-
接口概述
- 接口就是一种 公共的规范标准
- java 中的接口更多的体现在 对行为的抽象
-
接口的特点
-
使用
interface修饰。public interface 接口名{} -
子类使用
implements继承接口。public class 类名 implements 接口名{} -
接口不能被实例化,可以通过多态实例化。
-
接口中的 成员变量 默认被 final 修饰。
-
通过接口名可以访问 成员变量。
-
-
接口的 默认 修饰符:
- 成员变量:
public static final - 抽象方法:
public abstract
- 成员变量:
-
接口的实现类
- 要么重写接口中的 所有 抽象方法。
- 要么直接 设置 为抽象类。
-
接口的成员特点
- 接口没有构造方法和成员方法,只能 使用抽象方法。
- 通过重写接口里的抽象方法,来调用。
- 一个类如果没有父类,默认 继承 自 Object 类。
-
类和接口的关系
- 类和接口的关系:
- 实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口。
- 接口和接口的关系:
- 继承关系,可以单继承,也可以多继承。
- 类和接口的关系:
-
抽象类和接口的区别
- 成员区别:
- 抽象类:变量、常量、构造方法、抽象方法和非抽象方法。
- 接口:常量、抽象方法。
- 关系区别:
- 类与类:继承、单继承。
- 类与接口:实现、可以单实现、也可以多实现。
- 接口与接口:继承、单继承、多继承。
- 设计理念区别:
- 抽象类:对类抽象,包括属性、行为。
- 接口:对行为抽象,只要是行为。
- 成员区别:
-
注意事项:
- 使用接口的时候直接 new 子类,因为子类方法最多。
1.13、内部类(需要补充)
- 内部类:就是在一个类的内部再定义一个类。
- 一个 java 类中可以有多个 class 类,但是只能有一个 public class 类
1.13.1、成员内部类
public class Dome02 {
// 外部类私有属性
private int id = 10;
// 成员内部类
public class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
// 获得外部类的私有属性
public void getID(){
System.out.println(id);
}
}
}
// 调用成员内部类
public static void main(String[] args) {
Dome02 dome02 = new Dome02();
// 通过外部类实例化内部类
Dome02.Inner inner = dome02.new Inner();
inner.in();
inner.getID();
}
1.13.2、静态内部类(需要补充)
- 静态内部类:在成员内部类的修饰符里添加
static关键字。
public class Dome02 {
// 静态内部类
public static class Inner{
public static void in(){
System.out.println("静态内部类");
}
}
}
1.13.3、局部内部类
-
局部内部类:在方法里面创建的内部类
-
语法:
public class Dome01 { public void in(){ // 局部内部类 class Inner{ } } }
1.13.4、匿名内部类
- 没有名字初始化类,不用讲实例保存到变量中
public class Dome01 {
public static void main(String[] args) {
// 匿名调用 内部类中的方法
new Apple().eat();
// 匿名调用接口
new UserService() {
@Override
public void hello() { }
};
}
}
// 内部类
class Apple{
public void eat(){
System.out.println("1");
}
}
// 接口
interface UserService{
void hello();
}
-
类名作为形参和返回值:
-
方法的形参是类名,需要的是该类的对象。(就是 new 该类的类名)。
-
方法的返回值是类名,返回的值该类的对象。
// 返回值类名 public 类名1 get(){ 类名1 对象名 =new 类名1(); return 对象名; } // 调用 类名2 对象名1 = new 类名2(); 类1 对象名2=对象名1.类名2里的方法名(); 对象名1.类1里的方法名();
-
-
抽象类名作为形参和返回值:
-
抽象类名作为形参,需要的是子类的对象。(就是 new 该子类的类名)。
-
抽象类名作为返回值,返回值是子类的对象。
public 抽象类名 方法名(){ 抽象类名 对象名 =new 子类名(); return 对象名; }
-
-
接口名作为形参和返回值:
-
接口名作为形参,需要的是实现类(就是子类)的对象。
-
接口名作为返回值,返回值是实现类的对象。
public 接口名 方法名(){ 接口名 对象名 =new 子类(); return 对象名; }
-
-
内部类
-
内部类概述:
-
在一个类中再定义一个类。
-
格式:
public class 类名{ 修饰符 class 类名{} }
-
-
内部类的特点:
- 内部类可以直接访问外部类的成员,包括私有。
- 外部类要访问内部类的成员,必须创建对象。
- 内部类的定义:
- 在类的成员位置定义的:成员内部类。
- 在类的局部位置定义的:局部内部类。
-
成员内部类的调用:
-
外界调用内部类格式:
外部类.内部类 对象名=外部类对象().内部类对象(); // 这里的外部类是定义了内部类的 “类”。 -
私有内部类调用格式:
// 创建成员内部类 public class 外部类名{ private class 内部类名{ 类体; } public void 方法名{ 内部类名 对象名=new 内部类名对象(); 对象名.内部类中的方法名(); } }
-
-
局部内部类
-
概括
- 局部内部类是在方法中定义的内部类,外部无法直接访问,通过方法内部创建对象调用。
- 局部内部类可以访问外部类的成员和方法内的局部变量。
-
格式:
// 创建局部内部类 public class 外部类名{ public void 外部方法名(){ class 内部类名{ // 局部内部类不能使用 public 修饰符 public void 内部方法名(){ System.out.println("123"); } } 内部类名 对象名 =new 内部类名(); // new 局部内部类,new 方法必须在局部方法里面。 对象名.内部方法名(); } } // 调用局部内部类 pubic class 类名{ public static void main(String[] args){ 外部类名 对象名 =new 外部类(); // 通过 new 局部内部类的外部方法名调用。 对象名.外部方法名(); } }
-
-
匿名内部类
- 特点:
- 存在一个类或者接口,这里的类可以是具体的类也可以是抽象类。
- 匿名内部类也是局部内部类的一部分。
- 继承类或实现了该接口的子类匿名对象。
- 格式:
-
创建匿名内部类
// 在方法里面创建匿名内部类 new 类名或接口名(){ 重写方法; }; // 让匿名内部类可以调用 new 类名或接口名(){ 重写方法; }.重写的方法名; // 通过多态调用匿名内部类 类名 对象名 = new 匿名类名(){ 重写方法; }; 对象名.重写方法名(); //可以通过重写 对象名.重写方法名 实现多次调用 -
调用匿名内部类
类名 对象名 =new 类名(); 对象名.重写方法名(); -
匿名内部类在开发中使用
// 创建一个接口 public interface 接口名 { void 抽象方法名(); } // 创建操作类 public class 操作类名 { public void 方法名(接口名 参数){ 参数.抽象方法名(); } } // 创建测试类 操作类名 对象名 = new 操作类名(); 对象名.方法名(new 接口名() { @Override // 重构接口的抽象方法 public void 抽象方法名( { } });
-
- 特点:
-

浙公网安备 33010602011771号