基本的面向对象

面向对象

初识面向对象

什么是面向对象

◈面向对象编程(Object-Oriented Programming, OOP)

◈面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据。

◈抽象

◈三大特性:

◈封装

◈继承

◈多态

◈从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象

◈从代码运行角度考虑是先有类后有对象。类是对象的模板。

 

面向过程&面向对象

◈面向过程思想

◈步骤清晰简单,第一步做什么,第二步做什么...

◈面对过程适合处理一些较为简单的问题

 

◈面向对象思想

◈物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的 细节进行面向过程的思索。

◈面向对象适合处理复杂的问题,适合处理需要多人协作的问题!

 

◈对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。

 

回顾方法及加深

回顾方法的定义

回顾方法的调用

static:和类一起加载

无static:类实例化 之后才存在

◈引用传递:

 public class hello {
 //   引用传递:对象,本质还是值传递
     public static void main(String[] args) {
         Person person=new Person();
 ​
         System.out.println(person.name);//null
 ​
         hello.change(person);
 ​
         System.out.println(person.name);//张圣
    }
     public static void change(Person person){
         //person是一个对象
         person.name="张圣";
    }
 }
 //定义了一个Person类,有一个属性:name
 class Person{
     String name;
 }

对象的创建分析

类和对象的关系

◈类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物。

◈动物、植物、手机、电脑......

◈Person类、Pet类、Car类等,这些类都是用来描述/定义某一类具体的事物应该具备的特点和行为。

◈对象是抽象概念的具体实例

◈张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例。

◈能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念。

 

创建与初始化对象

◈使用new关键字创建对象

◈使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。

◈一个项目应该只存在一个main方法,而类可以创建很多。

主函数:

 package 类与对象;
 ​
 public class Application {
     public static void main(String[] args) {
 //       类是抽象的需要实例化、
 //       类实例化后会返回自己的一个对象!
 //       student对象就是Student类的一个具体实例!
         Student xiaoming = new Student();
         Student xiaohong = new Student();
 ​
         xiaoming.name="小明";
         xiaoming.age=3;
         System.out.println(xiaoming.name);
         System.out.println(xiaoming.age);
    }
 }

类:

 package 类与对象;
 ​
 public class Student {
         //属性:字段
         String name;
         int age;
 ​
         //方法
         public  void  study(){
             System.out.println(this.name+"在学习");
        }
 }

 

构造器详解

◈类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下俩个特点:

◈1.必须和类的名字相同

◈2.必须没有返回类型,也不能写void

 package JAVA;
 ​
 public class Application {
     public static void main(String[] args) {
 //       new 实例化一个对象
 ​
         Person person =new Person();
         System.out.println(person.name);
    }
 }

 

 package JAVA;
 ​
 public class Person {
 //一个类即使什么都不写,也会存在一个方法
 //   显示的定义构造器
     String name;
 ​
 //   实例化初始值
 //1.使用new关键字,本质是在调用构造器
 //   2.用来初始化值
     public Person() {
         this.name="张圣";
    }
 //   有参构造:一旦定义了有参构造,无参就必须显示定义
     public  Person(String name){
         this.name="zs";
    }
 }
  Person person =new Person();
  如果里面传入了参数如"ss",则输出zs,否则输出张圣,类似方法重载。
     
  可以用ALT+Insert快速生成方法

创建对象内存分析

 package JAVA;
 ​
 public class Application {
     public static void main(String[] args) {
         Pet dog = new Pet();
         dog.name="旺财";
         dog.age=3;
         dog.shout();
         System.out.println(dog.name);
         System.out.println(dog.age);
    }
 }
 package JAVA;
 ​
 public class Pet {
     String name;
     int age;
 ​
     public void shout(){
         System.out.println("叫了一声");
    }
 }

◈main方法在栈的底部,当main方法结束时,程序结束

◈栈里的dog,只是一个变量,相当于一个容器,存放pet()对象的地址 堆里的pet才是真正的具体的对象

 

 

面向对象三大特性

封装

◈该露的露,该藏的藏

◈我们程序设计要追求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方 法给外部使用。

◈封装(数据的隐藏)

◈通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。

◈属性私有,get/set

基本样例

 package JAVA;
 ​
 public class Application {
     public static void main(String[] args) {
         Student s1=new Student();
 ​
         s1.setName("张圣");
 ​
         System.out.println(s1.getName());
         s1.setAge(70);
         System.out.println(s1.getAge());
    }
 }
 package JAVA;
 ​
 public class Student {
     //   属性私有
     private String name;//名字
     private int id;//学号
     private char sex;//性别
     private int age;//年龄
 ​
     //   提供一些可以操作这个属性的方法!
 //   提供一些public的get、set方法
     //   get 获得这个数据
     public String getName() {
         return this.name;
    }
 ​
     //   set 给这个数据设置值
     public void setName(String name) {
         this.name = name;
    }
 ​
     public int getId() {
         return id;
    }
 ​
     public void setId(int id) {
         this.id = id;
    }
 ​
     public char getSex() {
         return sex;
    }
 ​
     public void setSex(char sex) {
         this.sex = sex;
    }
 ​
     public int getAge() {
         return age;
    }
 ​
     public void setAge(int age) {
         if(age>120||age<0){ //不合法的
             this.age=3;
        }
         else this.age=age;
    }
 }

◈封装的意义

◈1.提高程序的安全性 ◈2.隐藏代码的实现细节 ◈3.统一接口 ◈4.增加系统的可维护性

 

 

继承

 

◈继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。

◈extands的意思是“扩展”。子类是父类的扩展。

◈JAVA中类只有单继承,没有多继承!

◈继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。

◈继承关系的俩个类,一个为子类(派生类).一个为父类(基类)。子类继承父类,使用关键字extends来表示。

◈子类和父类之间,从意义上讲应该具有"is a"的关系.

 package JAVA;
 ​
 public class Application {
     public static void main(String[] args) {
         Student student= new Student();
 ​
         student.say();//student类中本没有say方法,因为其继承了Person,所以有
         System.out.println(student.money);
         
         student.setMoney(1000);
         System.out.println(student.getMoney());
    }
 }

 

 package JAVA;
 ​
 //person is 人:父类
 public class Person {
     public void say(){
         System.out.println("说了一句话");
    }
     public int money=10_000_000;
 //   public
 //   protected
 //   default
 //   private
 ​
     public int getMoney() {
         return money;
    }
 ​
     public void setMoney(int money) {
         this.money = money;
    }
 }

 

 package JAVA;
 ​
 //Student is 人:子类
 //子类继承了父类,就会有父类的全部方法!
 public class Student extends Person {
 ​
 }

 

 

object类

super

◈super注意点:

  1. super调用父类的构造方法,必须在构造方法的第一个

  2. super必须只能出现在子类的方法或者构造方法中!

  3. super和this不能同时调用构造方法!

     

◈Vs this:

◈代表的对象不同 this:本身调用者这个对象 super:代表父类对象的

◈应用前提 this:没哟继承也可以使用 super:只能在继承条件才可以使用

◈构造方法 this();本类的构造 super():父类的构造!

 package JAVA;
 ​
 public class Application {
     public static void main(String[] args) {
         Student student= new Student();
 ​
 //       student.test("zhangsheng");
 //
 //       student.test1();
    }
 }

 

 package JAVA;
 ​
 //Student is 人:子类
 //子类继承了父类,就会有父类的全部方法!
 public class Student extends Person {
 ​
     public Student(){
 //       隐藏代码:调用了父类的无参构造
         super();//调用父类的构造器,必须要在子类构造器的第一行
 //       this("hello");
 //       对this的调用同样要在构造器的第一个语句
         System.out.println("Student无参执行了");
    }
 ​
     private  String name="zs";
 ​
     public void print() {
         System.out.println("Student");
    }
     public void test1(){
         print();
         this.print();
         super.print();
    }
 ​
     public void test(String name){
         System.out.println(name);//zhangsheng
         System.out.println(this.name);//zs
         System.out.println(super.name);//张圣
    }
 }
 ​
 ​
 Person无参执行了
 Student无参执行了

 

 package JAVA;
 ​
 //person is 人:父类
 public class Person {
 ​
     protected String name="张圣";
 ​
     public Person() {
         System.out.println("Person无参执行了");
    }
 ​
     //   私有的东西无法被继承
     public void print(){
         System.out.println("Person");
    }
 }

}

 
重写
 

◈重写:需要有继承关系,子类重写父类的方法! 1.方法名必须相同 2. 参数列表列表必须相同 3.修饰符:范围可以扩大但不能缩小:public>Protected>Default>private 4.抛出的异常:范围,可以被缩小,但不能扩大; ClassNotFoundException --> Exception(大)

◈重写,子类的方法和父类必要一致;方法体不同!

◈为什么需要重写: 父类的功能,子类不一定需要,或者不一定满足!

 package JAVA;
 ​
 public class Application {
 //   静态方法和非静态方法区别很大
 //   静态方法:方法的调用只和左边,定义的数据有关
 //   非静态:重写
     public static void main(String[] args) {
         A a = new A();
         a.test();//A
 ​
         //父类的引用指向了子类
         B b = new A();//子类重写了父类的方法
         b.test();//B
 ​
    }
 }

 

 package JAVA;
 ​
 //继承
 public class A extends B{
     @Override//注解:有功能的注释!
     public void test() {
         System.out.println("A=>test()");
    }
 }

 

 package JAVA;
 ​
 //重写都是方法的重写,和属性无关
 public class B {
 ​
     public  void test(){
         System.out.println("B=>test()");
    }
 }

多态

◈动态编译:类型:可扩展性

◈即同一方法可以根据发送对象的不同而采用多种不同的行为方式。

◈一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多

◈多态存在的条件

◈有继承关系

◈子类重写父类方法

◈父类引用指向子类对象

◈多态注意事项 1.多态是方法的多态,属性没有多态 2.父类和子类,必须要有联系 3.存在条件:继承关系,方法需要重写,父类的引用指向子类对象!Father f1=new Son();

◈不能重写的方法 1.static 方法,属于类,它不属于实例 2.final 常量; 3.private 方法;

 package JAVA;
 ​
 public class Application {
     public static void main(String[] args) {
 //       一个对象的实际类型是确定的
 //       可以指向的引用类型就不确定了:父类的引用指向子类
 //       Student 能调用的方法都是自己的或者继承父类的
 ​
         Student s1 = new Student();
         Person s2=new Student();
 ​
 //       student 是实际类型,而其父类可以指向他,包括Person和Object
         Object s3=new Student();
 ​
 //       Person 父类型,可以指向子类,但是不能调用子类独有的方法
 //       能执行的哪些方法,主要看对象左边的类型,和右边关系不大~
         s1.run();
         s2.run();
         s1.eat();
         s2.eat();(×)
    }
 }

 

 package JAVA;
 ​
 public class Student extends Person {
 ​
     //       子类重写了父类的方法
     @Override
     public void run() {
         System.out.println("sun");
    }
 ​
     public void eat() {
         System.out.println("eat");
    }
 }

 

 package JAVA;
 ​
 public class Person {
     public void run(){
         System.out.println("run");
    }
 ​
 }

instanceof 和类型转换

◈注意点 1.父类引用指向子类的对象 2.把子类转换为父类,向上转型;直接转,丢失子类中原本可直接调用的特有方法 3.把父类转换为子类,向下转型;强制转换,向下转,会丢失父类被子类所重写掉的方法 4.方便方法的调用,减少重复的代码!简洁

 package JAVA;
 ​
 import org.omg.CORBA.Object;
 ​
 public class Application {
     public static void main(String[] args) {
 //类型之间的转化:父 子
 //高       低
 //       Person person = new Student;
 //       person.go();(×)
 //student将这个对象转换为Student类型,我们就可以使用使用Student类型的方法了!
 //高转低要强制转换
 ​
 //       方法一:用新的指向对象代替person
 //       Student student = (Student) person;
 //       student.go();
 ​
 //       方法二:强制转化
 //       ((Student)person).go();
 ​
 //       低转高自动转
 //       子类转化为父类可能会丢失自己的本来的一些方法
         Student student = new Student();
         student.go();
         Person person=student;
         person
 ​
 ​
 //       Object>Person>Student
 //       Object>Person>Teacher
 //       Object>String
 //
 //       Object object = new Student();
 //
 //       System.out.println(object instanceof Student);//ture
 //       System.out.println(object instanceof Person);//ture
 //       System.out.println(object instanceof Object);//ture
 //       System.out.println(object instanceof Teacher);//false
 //       System.out.println(object instanceof String);//false
 //       System.out.println("=======================================");
 //       Person person = new Person();
 //       System.out.println(person instanceof Student);//ture
 //       System.out.println(person instanceof Person);//ture
 //       System.out.println(person instanceof Object);//ture
 //       System.out.println(person instanceof Teacher);//ture
 ////       System.out.println(person instanceof String);//无法编译
 //       System.out.println("=========================================");
 //       Student student = new Student();
 //       System.out.println(student instanceof Student);//ture
 //       System.out.println(student instanceof Person);//ture
 //       System.out.println(student instanceof Object);//ture
 ////       System.out.println(student instanceof Teacher);//无法编译
 ////       System.out.println(student instanceof String);//无法编译
 ////       与左边的引用类型有关才能编译,与右边的关系决定了ture or false
 ​
    }
 }
 ===============================================================
 package JAVA;
 ​
 public class Teacher extends Person{
 ​
 }
 ================================================================
 package JAVA;
 ​
 public class Student extends Person {
     public void go(){
         System.out.println("go");
    }
 }
 =================================================================
 package JAVA;
 ​
 public class Person {
     public void run(){
         System.out.println("run");
    }
 ​
 }

 

Static

 

 package JAVA;
 ​
 public class Student {
 ​
     private static int age;//静态变量 多线程
     private double score;//非静态变量
 ​
 //   非静态方法和类一起加载,所以必须先创建类才能调用非静态方法
     public void run(){
 //       非静态方法可以调用静态方法中的所有东西
 //       go();
 ​
    }
 ​
     public static void go(){
 ​
    }
 ​
     public static void main(String[] args) {
         new Student().run();
         Student.go();
         go();
 ​
 ​
         Student s1 = new Student();
 ​
 //       静态变量可以直接使用类名去调用
         System.out.println(Student.age);
 //       System.out.println(Student.score);(×)非静态的字段不能直接使用类调用
         System.out.println(s1.age);
         System.out.println(s1.score);
    }
 }

 

 package JAVA;
 ​
 //如果该类被final定义了,就不能被继承了
 //public class Student extends Person (×)
 public /*final*/ class Person {
 ​
 //   赋初值
    {
         //代码块(匿名代码块)
         System.out.println("匿名代码块");
    }
 ​
     //与类一起加载,且只执行一次
     static{
         //静态代码块
         System.out.println("静态代码块");
    }
 ​
     public Person(){
         System.out.println("构造方法");
    }
 ​
     public static void main(String[] args) {
         Person person1 = new Person();
 //       依次输出静态代码块、匿名代码块、构造器
         System.out.println("=====================");
         Person person2 = new Person();
 //       依次输出匿名代码块、构造器
    }
 ​
 }

 

 package JAVA;
 ​
 //静态导入包~
 //就可以不用写Math
 import static java.lang.Math.random;
 import static java.lang.Math.PI;
 ​
 public class test {
     public static void main(String[] args) {
 //       生成随机数
 //       System.out.println(Math.random());
         System.out.println(random());
         System.out.println(PI);
    }
 }

抽象类和接口

抽象类

◈abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。

◈抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。

 

◈抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。

◈抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。

 

◈子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。

 

 package JAVA;
 ​
 //abstract抽象类: 类     extends:   单继承
 public abstract class Action {
 ​
 //   约束~有人帮我们实现
 //   abstract ,抽象方法,只有方法名字,没有方法的实现!
     public abstract void doSomething();
 //   1.不能new这个抽象类,只能靠子类去实现它;约束!
 //   2.抽象类中可以写普通方法
 //   3.抽象方法必须要在抽象类中
     public void hello(){
 ​
    }
 }

 

 package JAVA;
 ​
 //抽象类的所有方法,继承了它的子类,都必须要实现它的所有方法~除非它的子类也是abstract
 public class A extends Action{
 ​
     @Override
     public void doSomething() {
 ​
    }
 }

 

接口

◈普通类:只有具体实现 ◈抽象类:具体实现和规范(抽象方法)都有! ◈接口:只有规范!自己无法写方法~专业的约束!约束和分离:面向接口编程~

◈接口就是规范,定义的是一组规则,体现了现实世界中“如果你是...则必须能.….”的思想。如果你是天使,则必须能飞。如果你是汽车,则必须能跑。如果你好人,则必须干掉坏人;如果你是坏人,则必须欺负好人。

◈接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守。

◈OO的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么我们讨论设计模式都只针对具备了抽象能力的语言(比如c++、java、c#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。

◈声明类的关键词是class,声明接口的关键字是interface

 

 package JAVA;
 ​
 //抽象的思维~Java 架构师
 //interface 定义的关键字,接口都需要有实现类
 public interface UserService {
 ​
 //   常量!public static final
     int AGE=99;
 ​
 //   public static final int AGE=99;
     //   接口中的所有定义其实都是抽象的 public abstract
 ​
     void add(String name);
     void delete(String name);
     void update(String name);
     void query(String name);
 }

 

 package JAVA;
 ​
 public interface TimeService {
     void timer();
 }

 

 package JAVA;
 ​
 //抽象类:extents
 //类可以实现接口 implements 接口
 //Impl:implements 实现
 //实现了接口的类,就需要重写接口中的方法~
 ​
 //多继承,利用接口实现多继承~
 ​
 //ctrl+i 快速实现或者是ALT+ENTER
 public class UserServiceImpl implements UserService,TimeService{
 ​
     @Override
     public void add(String name) {
 ​
    }
 ​
     @Override
     public void delete(String name) {
 ​
    }
 ​
     @Override
     public void update(String name) {
 ​
    }
 ​
     @Override
     public void query(String name) {
 ​
    }
 ​
     @Override
     public void timer() {
 ​
    }
 }

◈接口的作用: 1.约束 2.定义一些方法,让不同的人实现~10--->1 3. public abstract 4. public static final 5.接口不能被实例化~,接口中没有构造方法~ 6. implements可以实现多个接口 7.必须要重写接口中的方法~

 

内部类及OOP实战

◈内部类就是在一个类的内部在定义一个类,比如,A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了。

◈1.成员内部类 ◈2.静态内部类 ◈3.局部内部类 ◈4.匿名内部类

 package JAVA;
 ​
 public class Outer {
     private int id=10;
     public void out(){
         System.out.println("这是外部的方法");
    }
 ​
     public class Inner{
         public void in(){
             System.out.println("这是内部类的方法");
        }
 ​
 //       获得外部类的私有属性
         public void getID() {
             System.out.println(id);
        }
    }
     public void method(){
 //       局部内部类
         class Inner{
 ​
        }
    }
 }
 ​
 //一个java类中可以有多个class类,但是只能有一个public class
 class A{
     public static void main(String[] args) {
 ​
    }
 }

 

 package JAVA;
 ​
 public class Application {
     public static void main(String[] args) {
         Outer outer = new Outer();
 //       通过外部类来实例化内部类
 ​
         Outer.Inner inner = outer.new Inner();
         inner.getID();
    }
 }

 

 package JAVA;
 ​
 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("1");
    }
 }
 interface UserService{
     void hello();
 }

 

posted @ 2022-04-10 10:03  疯的很正经  阅读(63)  评论(0编辑  收藏  举报