面向对象
当你什么时候接受了绿色,那你一定获得了一种智慧。
初始面向对象
- 面向过程思想
- 步骤清晰简单,第一步做什么、第二步做什么…
- 面向对象适合处理一些简单的问题
- 面向对象思想
- 物以类聚,分类的思维模式,思考问题首先回解决问题需要哪些分类。然后对这些分类进行单独思考,最后在对某个分类下的细节进行面向过程的思索。
- 面向对象适合处理复杂的问题,适合处理需要多人协作的问题!
- 对于描述复杂的事务,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到围观操作,我们还要面向过程的思路去处理。
什么是面向对象编程
- 面向对象编程(Object-Oriented Programming
OOP
) - 面向对象编程的本质就是:以类的方式组织代码,以对象形式的组织(封装)数据
- 抽象
- 三大特征
- 封装
- 继承
- 多态
- 从认识论考虑是现有对象后有类。对象,是具体的事务。类,是抽象的,对对象的抽象。
- 从代码角度是先有类后有对象。类是对象的模板。
类与对象的关系
-
类是一种抽象的数据类型,它是对某一类事物整体的描述/定义,但是并不能代表某一个具体的事物。
- 动物、植物、手机、电脑…
- Person类、Pet类、Car类等,这些类都是用来描述/定义某一类具体的事物应该具备哪些特点和行为。
-
对象是抽象概念的具体实例
-
张三就是一个人的具体实例,张三家里的旺财就是狗的一个实例。
-
能够体现出特点,展示出功能的是具体的实例,而不是一个抽象概念。
-
-
构造器
- 与类名相同,没有返回值。
- 作用:
- new对象的时候,本质是在调用构造器
- 用来初始化值
- 注意点
- 定义有参构造之后,如果想使用无参构造,必须显示的定义一个无参构造。
面向对象三大特性
- 封装
- 该露的露,该藏的藏
- 我们程序设计要追求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合就是仅暴露少量的方法给外部使用。
- 封装(数据的隐藏)
- 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。
- 记住这句话就够了:属性私有,get/set
- 封装的意义:
- 提高程序的安全性,保护数据。
- 隐藏代码的实现细节。
- 统一接口。
- 提高了系统的可维护性。
- 该露的露,该藏的藏
-
继承
CTRL + H
快捷键 CTRL + H 查看继承树。
-
继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
-
extends的意思是 “扩展” 。子类是父类的扩展。
-
Java中类只有单继承,没有的多继承!
-
继承是类和类之间的关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
-
继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。
-
子类和父类之间,从意义上讲因该有 “is a” 的关系。
-
子类继承父类就会拥有父类的全部方法(除private)。
-
object类
-
super - this
-
注意点
- super调用父类的构造器必须,必须在子类构造器的第一行。
- super必须只能出现在子类的方法或者构造方法中!
- super和this不能同时调用构造方法!
-
super 和 this 的区别
- 代表的对象不同
- this : 本身调用者这个对象。
- super:代表父类对象的引用
- 前提
- this: 没有继承也能使用
- super: 只能在继承条件才能使用
- 构造方法
- this: 本类的构造
- super: 父类的构造
- 代表的对象不同
-
-
方法重写
Override
Alt + Insert : Override;
- 需要有继承关系,子类重写父类的方法!
- 方法名相同
- 参数列表必须相同
- 修饰符:范围可以扩大但不能缩小:private --> protected --> default --> public
- 抛出的异常:范围可以被缩小,但不能扩大:Exception --> ClassNotFoundException
- 子类的方法必须和父类的一致;方法体不同!
- 为什么需要重写?:
- 父类的功能,子类不一定需要,或者不一定满足。
-
-
多态
instanceif
-
父类引用指向子类对象
-
同一方法可以根据发射对象的不同而采取多种不同的行为方式。
-
一个对象实际类型是确定的,但可以指向对象的引用的类型很多。
//一个对象的实际类型是确定的 new Student(); new Person(); //可以指向的引用类型就不确定了:父类的引用指向子类 //Student 子类型,能调用的方法都是自己的或者继承父类的! Student student = new Student(); //Person 父类型,可以指向子类,但是不能调用子类独有的方法。 Person student1 = new Student(); Object student2 = new Student(); //对象能执行那些方法,主要看左边的类型,和右边关系不大。 s1.eat(); ((Student) s2).eat();//子类重写了父类的方法,执行子类的方法。
-
-
多态存在的条件:
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类对象
-
多态注意的事项:
- 多态是方法的多态,属性没有多态。
- 父类和子类,有联系
类型转换异常! ClassCastException!
- 存在的必要条件:继承关系,方法需要重写,父类的引用指向子类的对象。
-
instanceof (类型转换)
- 把子类转换为父类,向上转型。
- 把父类转换为子类,向下转型。强制转换。
- 方便方法的调用,减少重复的代码!简介。
public static void main(String[] args) { //Object > String //Object > Person > Teacher //Object > Person > Student Object object = new Student(); //System.out.println(X instanceof Y); //能不能编译通过,在于X 和 Y 有没有父子关系。 System.out.println(object instanceof Student);//true System.out.println(object instanceof Person);//true System.out.println(object instanceof Object);//true System.out.println(object instanceof Teacher);//false System.out.println(object instanceof String);//false System.out.println("============"); Person person=new Student(); System.out.println(person instanceof Student);//true System.out.println(person instanceof Person);//true System.out.println(person instanceof Object);//true System.out.println(person instanceof Teacher);//false //System.out.println(person instanceof String); 编译报错 System.out.println("============"); Student student=new Student(); System.out.println(student instanceof Student);//true System.out.println(student instanceof Person);//true System.out.println(student instanceof Object);//false //System.out.println(student instanceof Teacher); 编译报错 //System.out.println(student instanceof String); 编译报错! }
-
static
public class Person { //2 { //代码块(匿名代码块) //不能主动执行 System.out.println("匿名代码块"); } //1 static { //静态代码块 //类加载即执行,永久执行一次 System.out.println("静态代码块"); } //3 public Person(){//构造器 System.out.println("构造方法"); } public static void main(String[] args) { Person person = new Person(); System.out.println("==========="); Person person1 = new Person(); }
//静态导入包 可之间调用方法 import static java.lang.Math.random; import static java.lang.Math.PI; public class Test { public static void main(String[] args) { System.out.println(random());//可之间调用方法 System.out.println(PI); } }
-
抽象类
//abstract 抽象类 public abstract class Action { //约束——有人帮我们实现。 //abstract,抽象方法,只有方法名,没有方法体。 public abstract void dos(); //1.不能new这个抽象类,只能靠子类去实现它:约束! //2.抽象类中可以有普通方法。 //3.抽象方法必须在抽象类中。 //抽象的抽象:约束。 //抽象类存在的意义:抽象共有属性,提高开发效率。 }
接口 interface
-
普通类:只有具体实现
-
抽象类:具体实现和规范(抽象方法)都有!
-
接口: 只有规范!自己无法写方法。
-
接口就是规范,定义的是一组规则,体现了现实世界中“如果你是…则必须能…”的思想。如果你是天使,则必须能飞。
-
接口的本质是契约,就像我们人间的法律一样。制定好后大家去遵守。
-
OOP的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么我们讨论设计模式的只针对具体了抽象能力的语言(
比如C++、java、C#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。
//interface 定义的关键字 , 接口都需要有实现类 public interface UserSvice { //接口中的属性其实都是常量,默认public static final int age=99; //接口中的所有方法其实都是抽象的,默认 public abstract void add(String name); void delete(String name); void update(String name); void query(String name); }
-
作用:
- 约束、定义一些方法,让不同的人实现。
- 接口不能被实例化,接口中没有构造方法。
- 可以实现多个接口
内部类
- 内部类就是在一个类中定义另一个类,比如,A类中定义一个B类,那么B类相对A类来说就是内部类,而A类相对B类就是外部类。
-
成员内部类
public class Outer { private int id=10; public void out (){ System.out.println("这是外部类的方法"); } public class inner{ public void in(){ System.out.println("这是内部类的方法"); } //获得外部类的id public void Getid(){ System.out.println(id); } } }
public class Application { public static void main(String[] args) { Outer outer = new Outer(); Outer.inner inner = outer.new inner(); inner.Getid(); } }
-
静态内部类
public class Outer { private int id=10; public void out (){ System.out.println("这是外部类的方法"); } public static class inner{ public void in(){ System.out.println("这是内部类的方法"); } } }
-
局部内部类
public class Outer { public void method(){ class Inner{ public void in(){ } } } }
-
匿名内部类
public class Test { public static void main(String[] args) { //没有名字初始化类,不用将实例保存到变量中。 new Apple().eat(); UserService userService = new UserService(){ @Override public void hello() { } }; } } class Apple{ public void eat(){ System.out.println("吃了一个苹果"); } } interface UserService{ void hello(); }