面向对象总结
01什么是面向对象
- 面向对象(oop)就是将属于同一类别的代码(对象)归类到一起的一堆代码。
001面向过程
**过程:**将一条大任务分成若干个小任务并且一一执行,直到将所有小任务全部完成才算结束。
- 所以我们的面向过程就是将代码一条一条的执行,并且每条都有不同的任务知道完成这个大的要求才算结束。
- 缺点:复杂性高的任务则不会很好的节约时间。
002面向对象
**对象:**将属于同一类型的或者是有着相似之处的东西或者物品归类到一起的过程。
- 缺点:简单型任务并不适用。
对于宏观的事物来说我们先将细节进行分类然后再一条条的执行细节。
我们的面向对象的核心思想就是将复杂的任务进行归类在归类的过程中再进行小细节的编写,然后再次按照分类完成的小任务完成大的工程。面向对象适合解决复杂性的问题,并且方便多人协助。
003面向对象编程(Object-Oriented Programming)
-
本质:以此类方式组织代码,以对象组织(封装)数据。
-
特性: 抽象
-
三大特性: 封装、继承、多态
02回顾方法
- Java方法是语句的集合,它们在一起会执行的一个功能。
- 方法是解决问题的步骤的有序组合。
- 方法包含到类或者对象之中。
- 方法在程序中创建其他地方引用。
- 编写方法的准则:方法的本意是一个功能,在程序中也就是实现某个功能的语句的组合。设计时一个方法只定义一个功能。
方法的创建:
- 我们常用的main其实就是一个方法。
public static void main(){ // void 表示空的意思
语句。。。
}
- 如果需要创建一个方法那么语法也和这个差不多
- 首先需要知道这个方法属于哪个类型。
- 然后我需要知道这个方法的名字。
- 根据情况而定需不需要参数如果只是一个需要执行的方法那肯定不需要,输入参数。
- 然后就可以定义内容啦。
public static int add(int a, int b){
// 固定语句 + 方法的类型 + 方法名 + (参数)
return a + b; // 返回 int类型a + int 类型 b 的结果。
}
03构成面向对象的过程
首先面向对象是个抽象的概念,举个例子你现在要去上厕所那么上厕所对你来说就是个抽像的概念假设你现在在床上躺着那么你首先需要起床然后穿鞋走到厕所到厕所之后解开腰带才可以开始上厕所。
将你上厕所的过程用面向对象来编写的话大体的概念就是,首先你有个名为上厕所的一个大类,里面有你起床、穿鞋、走到厕所、解开腰带的小的执行方法,最后在用一个开始上厕所这几个步骤构成的一个大的事件就是你上厕所。
好的那么现在你是不是已经对面向对象有个大体的概念了对吧,很像方法对吧当然如果面向对象和方法一样功能不就重复了嘛那为什么还要面向对象呢直接使用方法不久完了,那么假设你现在手脚都受伤了呢?需要别人帮你起床帮你穿鞋…等一系列操作,得出一个结论那就是面向对象是一个用于归类可共同协作的一个编写代码的方法。
或者说我们可以说的通俗易懂写:面向对象就是一种分类方式
04回顾方法的调用
- 我们知道静态方法就是在后面添加了static的方法。非静态方法就是没有static的方法有static的方法是可以直接通过类名调用的;非静态方法是不能直接通过类名调用的调用需要实例化。
public class Demo01 {
public static void add(){
System.out.println("静态方法");
}
}
public class Demo01 {
public void add(){
System.out.println("非静态方法");
}
}
public class Demo02 {
public static void main(String[] args) {
Demo01.add(); // 静态方法的调用
}
}
public class Demo02 {
public static void main(String[] args) {
Demo01 Demo01 = new Demo01(); // 实例化
Demo01.add(); // 非静态方法的调用
}
}
-
另外如果有两个静态方法两方法是可以互相调用的
-
同理如果有两个非静态方法也是可以互相调用的
-
但是如果有一个静态方法和一个非静态方法是无法互相调用的,因为非静态方法在没实例化之前是不存在的。
-
形式参数:没有返回的参数值
-
非形式参数: …
05类和对象的关系
类:类是对事物的一种抽象的数据类型,他是对一件事物的整体做出的描述/定义但是并不代表着一个具体的事物。
001创建一个面向对象
注意事项:
- 创建一个类时不要再该类文件下进行测试
- 一个包中如果含有类应该建立一个名为 Application 的文件进行测试。
定义一个类:
public class Student { // 定义一个学生类
// 属性、字段
String name; // 学生类的姓名
int age; // 学生类的年龄
// 方法
public void study(){ // 学生类的行为
System.out.println(this.name +"学生在学习"); // this 当前的对象的属性
}
}
002使用new的调用与初始化
- 我们在使用关键字new来创建调用类的时候除了分配好空间后还分配好了初始值。
调用一个对象:
public class Application {
public static void main(String[] args){
Student student = new Student();
}
}
- 调用类需要实例化,我们使用new 来实例化我们的对象。
- 实例化后会返回到自己的对象
- Stident 类产生了一个student对象
当然我们的类是肯定可以生成多个对象的
public class Application {
public static void main(String[] args){
Student xiaoming = new Student();
xiaoming.name = "小明";
xiaoming.age = 8;
}
}
假设我们没有提前去定义name的话,因为我们在属性中定义的name属于的是字符串类型去调用的话则会默认返回一个null这就是刚刚说到的使用new回馈的初始值。
003构造器
- 构造器也称为构造方法创建对象时必须调用。
- 生成构造器:Alt + insert(快捷键)
特点:
- 必须和类的名字相同
- 没有返回类型也不能写void
在当我们使用一个类时,即使说里面什么都没有写依旧可以执行打开class文件后会自动生成一个方法。这个方法就是他的构造器。
作用: 使用new关键字时必须要有构造器,如果没有构造器程序无法执行。
分类:
- 有参构造器:
public class Person {
String name;
public Person(String name) {
this.name = "秦始皇";
}
}
- 无参构造器:
public class Person {
// 一个类上即使什么也不写也会生成一个方法
String name;
public Person(){}
public Person(String name){
this.name = name;
}
}
- 必须定义一个无参才可以运行有参
- 定义有参时只需要将无参空着即可
06封装
封装: 顾名思义就是将一个东西装起来。
-
该露的露该藏的藏。
- 程序设计追求高内聚,低耦合。
- 高内聚:类的内部数据自己完成不允许外部干涉。
- 低耦合:只暴露少量的方法给外部调用。
-
封装:数据的隐藏
- 通常应禁止直接访问一个对象中数据的直接表示,应通过操作接口来访问,这称为信息的隐藏。
-
属性私有,get/set
封装重点用于属性很少用于方法。
封装的使用
要先使用首先要先定义封装嘛不就是隐藏嘛隐藏就是需要私有化嘛所以要创建一个封装只需要多加入一个私有化即可。
public class Sudent {
// private:私有化属性,也就是不让随便调用随便更改的属性
private String name;
private int age;
}
既然是可以创建那必然是要使用的,由于私有化后的属性有些特殊所以他的调用方式也会不太一样。
- 获取 get 在使用一个私有化属性的时候需要的就是先获取元素当然这个可是新的知识点怎么可能随随便便就获取了呢。
- 设置 set 在私有化中也就是在封装的过程中是可以提前设置元素的。
- 只有同时具有set和get才可以使用一个封装。
// 当前类定义
public class Sudent {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 外部调用
public class Application {
public static void main(String[] args) {
Sudent qinjiang = new Sudent();
qinjiang.setName("秦将");
System.out.println(qinjiang.getName());
}
作用:提高代码的安全性、为代码隐藏了更多的细节、统一的接口共有一个接口即可、系统的可维护性增加了。
重载:使用同一个名字使用任何的参数。
07继承
-
继承的本质是对一批类进行定义,
-
extends 是扩展的意思子类是父类的扩展。
-
Java中只有单继承没有多继承。
-
继承是类和类之间的关系除了继承以外类和类之间的关系有:依赖、组合、聚合。
-
继承关系的两个类一个为派生类(子类),一个为基类(父类)。使用关键字extends
继承是一个特别重要的东西他的作用是将一个大的类可以分成若干个小类,比说学生和老师都属于人类他们都可以继承人类这个父类,学生类、和老师类就是人类父类的两个子类。
继承的使用
- 只是概念的话是说不清的实践永远是最好的证明
首先我们先定义一个Person(人类)的类
public class Person {
public void say(){
System.out.println("说了一句话");
}
}
然后我们分别新建两个类一个类名为Sudent(学生)和Teacher(老师)的类并且让他们继承Person类
public class Sudent extends Person{
}
public class Teacher {
}
那么我们调用的时就可以调用Person上的方法。不过继承是无法调用属性的我们要在定义属性之前添加上public才可以定义属性。
public class Person {
public String name;
public void say(){
System.out.println("说了一句话");
}
}
- 不同的关键字用于程序的调用规则也是不一样的,这其中包含着权限的问题!!!!
// public 公共
// protected 当前
// default 默认
// private 私有
打开继承方法树:CTRL + H
注意:在Java中所有的类都默认继承object类,这是Java中的一个底层类。
Super关键词
- super: 可以使子类直接调用父类的属性
父类:
package com.meng.oop.demo06;
public class Person {
protected String name = "kuangshen";
}
子类:
package com.meng.oop.demo06;
public class Sudent extends Person{
private String name = "qinjiang";
public void test(String name){
System.out.println(name); // 传递到的数据
System.out.println(this.name); // 当前类的数据
System.out.println(super.name); // 父类的数据
}
}
调用:
package com.meng.oop;
import com.meng.oop.demo06.Person;
import com.meng.oop.demo06.Sudent;
public class Application {
public static void main(String[] args) {
Person person = new Person();
Sudent sudent = new Sudent();
sudent.test("黄浩");
}
}
super其实就是调用父类的结构(方法)
01super注意点
- super是调用父类结构方法
- super不能和this一起使用
- super只能出现在一个子类方法或者结构方法中
02super于this的区别
- this:本类的其他方法
- super:代表父类对象应用
前提:
this:没有继承也可以使用
super:在继承条件下才能使用
构造方法:
this();:本类的构造
super();:父类的构造
08方法的重写
重写:只能用于静态方法而且是公开的方法还需要相同的方法名,并且是继承的子类要重新写入的是父类的方法。
在开始之前还是要再说一遍静态方法和非静态方法的,首先我们知道静态方法和非静态方法有很大的不同
-
静态方法:调用的数据定义类型。
-
非静态方法:调用的非定义类型。
- 重写这个定义说起来也简单,我们先定义一个A类和B类,然后让A类继承B类并写入一个非静态方法。
public class A extends B{
public void test(){
System.out.println("A=>test");
}
public class B{
// 重写只运用于方法之中
public void test(){
System.out.println("B=>test");
}
}
- 这个时候我们发现IDJE页面上A类和B类旁边分别出现的不同的符号。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6PR3usv6-1672408047437)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20221120151944863.png)]
- 这就是生成了一个重写啦,然后我们来试着调用。我们发现父类指向了子类的方法。
public class Application {
public static void main(String[] args) {
A a = new A();
a.test();
B b = new A();
b.test();// 本应指向B类的方法却指向了A类
}
}
- 到这里重写的定义也就清晰啦,无非就是一个在子类中在不改变父类本身的情况下修改方法的操作
- 简单来说也就是将继承来的东西在我这里做出改变为了让他传承和变得更好
09方法的多态
多态:指方法的各种形态。作用就是使得对象的可扩展性变的更强
- 多态在Java中指的是在一个对象中编写对象的各种用法
- 也就是将继承、重写、封装组合到一起的一种写入方式。
方法的多态注意事项:
- 多态是方法的多态属性则没有多态
- 父类和子类虽然有着联系但是不能直接调用
- 也就是说一个方法在子类中拥有但父类中却没有
- 想要直接调用是不可行的需要强制转换成子类类型才可以将其调用
多态存在的条件:
- 有继承关系
- 子类重写父类的方法
- 父类引用指向子类的对象
public class Application {
public static void main(String[] args) {
Student s1 = new Student(); // 本身调用
Person s2 = new Student(); // 使用父类调用
Object s3 = new Student(); // 使用项目类调用
// 那么产生一个问题,调用的先后顺序是什么呢?
// 对象可以执行的方法主要看对象左边的类型。和右边的关系不大
s1.eat(); // 调用本身
s1.run(); // 调用本身
s2.run(); // 重写
((Student)s2).eat(); // 强制转换
((Student)s3).eat();
}
}
扩展关键字
instanceof 关键词----引用类型
Ait + 回车 引用当前类型
- 判断一个对象是什么类型以及当前对象与其他对象的是否有连接(继承)关系
用法:
- 将两个对象中间套上instanceof语句。
public class Application {
public static void main(String[] args) {
Object object = new Student();
System.out.println(object instanceof Person); // object 类是 person 类的 父类
System.out.println(object instanceof Student); // object 类是 student 类 父类 的 父类
System.out.println(object instanceof Object); // object 类是 object 类
System.out.println(object instanceof Teacher); // 虽然 object 类 是 Teacher 类 的父类 但是 与 新建的 Student 无关
System.out.println(object instanceof String); // 虽然 object 类 是 String 类 的父类 但是 与 新建的 Student类 的父类 Person 类 无关
System.out.println("====================================================");
Person person = new Student();
System.out.println(person instanceof Person);
System.out.println(person instanceof Student);
System.out.println(person instanceof Object);
System.out.println(person instanceof Teacher);
// System.out.println(person instanceof String); 直接报错因为 person 类是与String 类 是完全没有关系的
System.out.println("====================================================");
Student student = new Student();
System.out.println(student instanceof Person);
System.out.println(student instanceof Student);
System.out.println(student instanceof Object);
// System.out.println(student instanceof Teacher); // 直接报错因为 student 类 与 teacher 类完全没有关系
// System.out.println(student instanceof String); // 同上
}
对象的强制转换
public class Application {
public static void main(String[] args) {
// 类与普通的类型一样,等级比较高的类转换成等级低的类不需要强制转换
Person person = new Student();
// 但是无法直接调用子类的函数
// person.go();
// 使用需将其转换(高转低强制转换)才可使用子类方法
Student student = (Student) person;
((Student) person).go();
student.go();
// 子类转换成父类可能会丢掉某些方法
}
}
static
-
在文章的开始我们就经常提到静态变量和私有变量是有区别的
-
简单来说添加static的变量或者类型是个可以在Java全局中使用的,也就是全局变量
- 也就是说在Java中任何地方都可以被使用、调用的变量或者方法。
-
不加static变量则是只能在一个方法或者个类中局部使用的,也就是局部变量
- 也就是说在Java中的某一个范围内才可以使用、调用的变量或者方法。
-
-
除了添加不添加static以外调用方法也是有区别的。我们先看到了咱们有两组不同的变量和方法
public class Student {
private static int age; // 静态私有变量
private double score; // 非静态私有变量
public void run(){
System.out.println("run");
}
public static void go(){
System.out.println("go");
}
}
- 调用的规则如下:
public static void main(String[] args) {
Student s1 = new Student();
// 属性
System.out.println(Student.age); // 类变量
// System.out.println(Student.score); // 类变量不难调用非静态变量
System.out.println(s1.age);
System.out.println(s1.score);
// 方法
new Student().run(); // 非静态方法
Student.go(); // 静态方法
// 非静态的方法可以去调用静态方法中的东西;静态方法可以调用静态方法不可以调用非静态方法
}
代码块
匿名代码块:
public class Person {
{
// 匿名代码块
}
}
静态代码块:
static {
// 静态代码块
}
构造方法:
public person{
// 构造方法
}
三种不同的代码块执行的先后顺序是:
- 静态代码块
- 匿名代码块
- 构造方法
需要注意的是静态代码块只会执行一次,而其他两类会在对象启动的时候进行执行。
10抽象类
abstract关键字一般是用来修饰方法的,如果使用abstract修饰符修饰类那么这个类就是一个抽象类。
- 抽象类中可以没有抽象方法,但是抽象方法一定有抽象类。
- **不可new,**抽象类是继承到的
- 抽象方法只有声明没有方法的实现
- 方法通过子类来实现
- 子类继承抽象类时,必须实现抽象类中未实现的东西否则该子类仍为抽象类
01创建抽象类
- 抽象类
- 抽象方法
- 接口
- 三个要素构建抽象类
// abstract 抽象类
public abstract class Action {
// 抽象方法:只有方法名没有实现过程
public abstract void doSomething();
}
02继承抽象方法
-
继承抽象方法后必须要实现方法除非子类也是抽象类
-
继承抽象方法需要必须要重写类
-
继承后即可以实现
public class A extends Action{
@Override
public void doSomething() {
}
}
- 问题:既然抽象类的本质是个类那么他肯定是会需要继承的,目前已知extends为单继承但是Java中是没有多继承的。
- **注意!!!**接口是可以进行多继承的.
抽象类的特点
- 不能使用new关键字调用只能靠子类去实现它。
- 抽象类可以带有正常的方法
- 抽象方法必须只能在抽象类中
个人难点看法
抽象类是否存在构造器?
-
抽象类是虽然不可以new但是抽象类是存在构造器的
- 抽象类本身不能new
- 但是继承方法的实现可以靠本身以外的子类来调用
- 调用的过程会使用到自己的子类
-
抽象类更像是一个实现前的预设,用于暂时定义。
- 避免了多种功能的冲突起到约束作用
- 也可以在实验期使用
11接口
-
**普通类:**有着具体的实现方法
-
**抽象类:**具体实现方法和规范实现方法都有。
- 规范实现方法:抽象方法
-
**接口:**极其特殊只有规范方法。
-
接口也是一种规范,是一个比抽象类更严格的一种限制规范。
interface关键字是用来修饰一个接口的,接口是一个特殊的文件不属于class。
01创建接口
public interface UserService {
// interface就是接口的关键字,是一个不同与类的新的定义
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1EGa36DX-1672408047440)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20221230190655244.png)]
-
通过IDEA可以看出来文件的图标已经变了就说明它并不是一个class。
-
注意接口中不能直接创建方法,则是可以创建一种简单方法。
public interface UserService {
void run(); // 简单方法:处位置不写默认为 public abstract void run();
}
02实现接口
接口都需要一个实践类,通过实践类调用。
// 类通过implements 实现接口; 接口名+Impl为标准实现方法;接口的实现也是需要重写的
public class UserServiceImpl implements UserService{
@Override
public void add(String name) {
}
@Override
public void update(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void query(String name) {
}
}
- 需要补充的是如果想要实现接口就必须重写接口的所有方法。否则报错!!!!
利用接口实现多继承
- 首先我们知道在Java中是没有多继承的但是接口是可以多个一起调用的由此我们利用这个特性来实现多继承
// 第一个接口
public interface UserService {
void add(String name);
void update(String name);
void delete(String name);
void query(String name);
// 内置四个简单函数(规范)
}
// 第二个接口
public interface TimeService {
void time();
}
// 内置一个简单函数(规范)
- 然后直接进行继承并重写即可
- 在这里再次强调:必须重写所有接口的规范才可以进行implements调用
public class UserServiceImpl implements UserService,TimeService{ // 注意这一行哦~~
@Override
public void add(String name) {
}
@Override
public void update(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void query(String name) {
}
@Override
public void time() { // 全部全部,是包括所有的接口!!!!
}
-
注意:在Java中所有方法的定义都是一个变量,然而所有属性(int、char…)都是一个常量。
- 也就是再说,方法有可能会在某些时候不能直接使用或者编写
- 但是属性是在任意地方都可以使用编写定义的
-
接口的作用(总结)
- 用于约束
- 可以用于定义一些方法让不同的人实现
- 方法都是 public abstract
- 常量都是 public static final
- **接口也不能被实例化!!!**因为接口中没有构造方法。
- 利用implements可以实现多个接口的使用
- 必须要重写方法