首页 > 编程语言 >五 Java面向对象

五 Java面向对象

时间:2022-09-26 18:44:43浏览次数:66  
标签:Java 子类 void System 面向对象 println public out

面向对象

初识面向对象

面向过程&面向对象

面向过程思想: 步骤清晰简单,第一步做什么,第二步做什么…
面对过程适合处理一些较为简单的问题

面向对象思想 : 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,

​ 然后对这些类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。
​ 面向对象适合处理复杂的问题,适合处理需要多人协作的问题!

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

什么是面向对象

  • 面向对象编程(Object-Oriented Programming ,OOP)
  • 面向对象编程的本质就是:以类的方式组织代码,以对象的方式组织(封装)数据。
  • 核心思想:抽象
  • 三大特性:封装、继承、多态
  • 从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象
  • 从代码运行角度考虑是先有类后有对象。类是对象的模板。

方法回顾和加深

回顾方法的定义

public class Dome01{
    //public类的名字应该和java文件名相同
    public static void main(String[] args){
        
    }
    //方法名应该见名知意,驼峰原则
    //参数列表 (参数类型,参数名)...
    /*
    修饰符 返回值类型 方法名(形参){
        //方法体
        return 返回值;//void 不返回值 return;
    }
    */
    public static int getMaxNum(int a,int b){
        return a>b ? a : b;
    }
    public static String getHelloWorld(){
        return "hello,world";
    }
    public void readFile(String file) throws IOException{
        
    }
}

回顾方法的调用

静态与非静态

静态方法 static调用时类名+方法名

非静态方法调用需要实例化。

//跨文件(类)调用

Student.say();//静态方法

//非静态方法
Student stu = new Student();
stu.say();

//在同一个文件(类)中
//非静态可以相互调用,静态也可以相互调用,但静态不可以调用非静态的,非静态可以调用静态的

值传递与引用传递

//值传递
public static void main(String[] args) {
    int a = 1;
    System.out.println(a);
    change(a);
    System.out.println(a);
    //  1    
    //  1
}
public static void change(int a){
        a = 10;
}
//引用传递:对象,本质还是值传递.有点像指针
public class hello {
    public static void main(String[] args) {
        Person aaa = new Person();
        System.out.println(aaa.name);
        change(aaa);
        System.out.println(aaa.name);    
       }    
}
public static void change(Person person){
        person.name = "tiangong";
    }

对象的创建分析

类与对象的关系

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

    ​ 动物、植物、手机、电脑…

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

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

​ 张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例。
​ 能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念。

创建和初始化对象

  • 使用new关键字创建对象
  • 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。
//this是实例本身,哪个实例调用,this就指哪个实例
//快捷键  new 类名.var 加回车
//一个项目应该只存在一个main方法。
//一个java文件只能有一个public类
//对象是类的实例
public class Dome01 {
    public static void main(String[] args) {
        Cat mimi = new Cat();
        Cat dajv = new Cat();
        mimi.name = "咪咪";
        dajv.name = "大橘";
        mimi.bark();
        dajv.bark();
    }  
 //换文件,或者把下面这个类的public修饰去掉
public class Cat{
    //属性,字段
    String name;
    int age;
    
    //方法(行为)
   public void bark(){
        System.out.println(this.name+ " :喵~ 喵~~~~");//这里加不加this好像都好使的
    }
    
}


构造器详解

当我们开了一个新的空的class Person类,但我们依然可以new出来一个对象。

从class文件中看,一个类即使什么都不写,它也会存在一个方法,这就是构造方法,也叫构造器

  • 类中的构造器也称为构造方法,是在进行创建对象的时候必须调用的。并且构造器有以下两个特点:
    必须和类的名字相同
    必须没有返回类型,也不能写void

  • 构造器必须要掌握

    class Person{
        
        String name;
        //构造器的作用
        //1.使用new关键字,本质实在调用构造器
        //2.实例化初始值.
        public Person(){
            this.name = "天工";
        }
        //有参构造,一旦定义了有参构造,无参就必须显示
        public Person(String name){
            this.name = name;
        }
    }
    
    //另一边的main方法
    Person R = new Person("RockMusic");
    System.out.println(R.name);
    

    idea快捷键:alt + insert 生成构造器

    然后选Constructor.接下来选OK为有参,选Select None为无参

创建对象内存分析

image-20220215205259857

新的对象可以直接从静态方法区调用方法。

面向对象三大特性

封装

  • 该显的显,该藏的藏。
  • 我们程序设计要追求“高内聚,低耦合”

​ 高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;
​ 低耦合:仅暴露少量的方法给外部使用。

  • 封装(数据的隐藏)
    通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。
  • 记住这句话就够了:1.属性私有 2. get/set
//不知道为什么,一个文件里,能有除public class之外的两个class.

//属性私有
class Student{
    private String name;
    private int age;
}//这个样子,就不允许更改新创建出来的对象的属性

//     getter / setter
//提供一些可以操作这个属性的方法
//提供一些public的get、set方法
//get 获得这个数据 
//set 设置这个数据
class FreshMan{
         private String name;
         private int age;

         public String getName(){
             return name;
          }
         public void setName(String N){
             name = N;
           }
    //idea 有快捷键 alt + insert.选择getter and setter,再选择属性,点ok.
         public int getAge() {
              return age;
              }

          public void setAge(int age) {
              //对于年龄而言,-1岁和过大的岁数是不符合实际情况的,所以施加判断
              if(age>120 || age<0){
                     System.out.println("输入的年龄不合法");
               }else{
                     this.age = age;
                }
          }  
}    

//main这边
FreshMan y = new FreshMan();
y.setName("hhh") ;
System.out.println(y.getName());


封装的优点:

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

继承

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

  • extends的意思是“扩展”。子类是父类的扩展。

  • JAVA中类只有单继承,没有多继承! 一子只一父,一父可多子。

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

  • 继承关系的俩个类,一个为子类(派生类),一个为父类(基类)。

  • 子类继承父类,使用关键字extends来表示。
    在Java中,所有的类都默认直接或者间接继承Object类(始祖)

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

//  子类可以继承父类的default及以上的的属性和方法。私有的东西只能隐式继承,不能调用。
//   public  公共的
//   protected 受保护的
//   default 默认
//   private 私有
public class Person {
    String name;
    protected String myName = "明月";
    int age;
    String sex;

    public void shoot(){
        System.out.println(this.name + "说:大梦平生");
    }
    public void print(){
        System.out.println("Person");
    }
    public String getName(){
        return name;
    }
    public void setName(String N){
        this.name = N;
    }
    
    public int getAge() {
        return age;
}
public class YoungMan extends Person{


    public void shoot(){
        System.out.println(this.name + "说:潜龙毋用");
    }
}
public class OldMan extends Person{
}
public class Me extends Person{
     private String myName = "清风";

     public void test(String n){
          System.out.println(this.myName);
          System.out.println(super.myName);
          System.out.println(n);
     }
    public void print(){
          System.out.println("Me");
     }
     public void test2(){
          print();
          this.print();
          super.print();
     }
}

public class hello {
    public static void main(String[] args) {
        YoungMan child = new YoungMan();
        child.setName("小孩");
        child.setAge(10);
        child.shoot();
        OldMan theOld = new OldMan();
        theOld.setName("耄耋");
        theOld.shoot();
        
        Me mySelf = new Me();
        mySelf.test("我");
        
        mySelf.test2();
    }

}
   //小孩说:潜龙毋用
   //耄耋说:大梦平生
   //清风
   //明月
   //我
    //Me
    //Me
    //Person

子类创建一个对象是,先调用父类构造方法,再调用子类构造方法。//super(); 子类方法();

所以调用父类构造器,必须要在子类构造器的第一行

super注意点

  1. super调用父类的构造方法,必须在构造方法的第一个
  2. super 必须只能出现在子类的方法或者构造方法中!
  3. super和 this不能同时调用构造方法!(因为super();和this();都必须在第一行)

this VS super

  1. 代表的对象不同:
    • this:本身调用者这个对象
    • super:代表父类对象的
  2. 应用前提
    • this:没有继承也可以使用
    • super:只能在继承条件才可以使用
  3. 构造方法
    • this();本类的构造
    • super():父类的构造

重写

重写是方法的重写,和属性无关

public class B {
    public static void test(){
        System.out.println("B");
    }
}
public class A extends B{
    public static void test(){
        System.out.println("A");
    }
}
public class C {
    public static void main(String[] args) {

        //静态方法调用只和左边,定义的数据类型有关
        A a = new A();
        a.test();        //A

        // 父类的引用指向了子类
        B b = new A();
        b.test();     //B
    }
}
//再写一下A
public class A extends B{
    //快捷键,alt + insert 点override methods
    @Override    //这是一个注解,有功能的注释
    public  void test(){
        super.test();
    }
}

//然后我们修改内容
public class A extends B{
    @Override    
    public  void test(){
        System.out.println("A");
    }
}
//再运行时,都变成了A
//所以静态方法和非静态方法不一样
//非静态 :重写

重写:需要有继承关系.子类重写父类的方法!

特点:

  • 方法名必须相同

  • 参数列表列表必须相同

  • 修饰符:范围可以扩大但不能缩小 Public>Protected>Default>Private

  • 抛出的异常:范围,可以被缩小,但不能扩大;

​ Exception(大) -->ClassNotFoundException重写,子类的方法和父类必要一致;方法体不同!

为什么需要重写?

  • 父类的功能,子类不一定需要,或者不一定满足!

快捷键: Alt + Insert ; ( override;)

java的访问权限
public : 对所有类可见。使用对象:类、接口、变量、方法
protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)

多态

  • 即同一方法可以根据发送对象的不同而采用多种不同的行为方式。
  • 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多
  • 多态存在的条件
    • 有继承关系
    • 子类重写父类方法
    • 父类引用指向子类对象
  • 注意:多态是方法的多态,属性没有多态性。
  • instanceof 引用类型的类型转换
//一个对象的实际类型是确定的
//但指向的引用类型是不确定的:父类的引用指向子类。
YoungMan s1 = new YoungMan();//子类能调用的方法都是自己的或者继承子类的。
Person s2 = new YoungMan();//父类,可以指向子类,但是不能调用子类独有的方法
Object s1 = new YoungMan();
//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大。
//子类重写了父类的方法,就会执行子类的方法。

//举个例子,YoungMan里有非静态方法,走和爬
//Person 里只有非静态方法,走
s1.crawl();//可执行
s2.crawl();  //不可执行
((YoungMan) s2).crawl();// 强制类型转换   可执行

多态注意事项

  1. 多态是方法的多态,属性没有多态
  2. 父类和子类,有联系。如果没有关系转换,会报错类型转换异常! CLassCastException
  3. 存在条件:继承关系,方法需要重写,父类引用指向子类对象!
Father f1 = new Son();

不能重写的方法

  1. static 方法,属于类,不属于实例。
  2. final 常量
  3. private方法

instanceof

boolean result = obj instanceof Class;  

其中 obj 为一个对象,Class 表示一个类或者一个接口,当 obj 为 Class 的对象,或者是其直接或间接子类,或者是其接口的实现类,结果result 都返回 true,否则返回false。

注意:编译器会检查 obj 是否能转换成右边的class类型,如果不能转换则直接报错(编译不通过),如果不能确定类型,则通过编译,具体看运行时确定。

/* 放一下各个类的关系,作为前提条件
Object > String
Object > Person > Teacher
Object > Person > Student
*/
Object obj = new Student();
System.out.println(obj instanceof Student);//true
System.out.println(obj instanceof Person);//true
System.out.println(obj instanceof Object);//true
System.out.println(obj instanceof Teacher);//false
System.out.println(obj instanceof String);//false

Person ren = new Student();
System.out.println(ren instanceof Student);//true
System.out.println(ren instanceof Person);//true
System.out.println(ren instanceof Object);//true
System.out.println(ren instanceof Teacher);//false
//System.out.println(ren instanceof String);编译报错

Student stu = new Student();
System.out.println(stu instanceof Student);//true
System.out.println(stu instanceof Person);//true
System.out.println(stu instanceof Object);//true
//System.out.println(stu instanceof Teacher);//编译报错
// System.out.println(stu instanceof String);//编译报错

编译器检查是看引用类型,运行结果是看引用对象的实际类型。即编译能否通过看左边引用类型说明,运行结果看右边实际对象构造。

类型转换

public class Application {
    public static void main(String[] args) {
        //类型转换  父  子
        //高   <--------- 低
        Person wuhu = new Student(); //自动向上类型转换
        wuhu.run();    //调用父类方法
        //obj.say();    向上类型转换丢失子类的方法
        ((Student) wuhu).say();//父类转化为子类,强制向下类型转换
        ((Student) wuhu).run();//子类可以调用父类的方法
    }

多态小结:

  1. 父类引用指向子类的对象
  2. 把子类转换为父类,自动向上类型转换,会丢失子类自己的方法。
  3. 把父类转换为子类,向下类型转换,强制转换,可以调用父类的方法。
  4. 方便方法的调用,减少重复的代码,简洁。

static

public class Student {
    private static int age;
    private double score;
    public void run(){
    }
    public static void go(){
    }
    public static void main(String[] args) {
        Student ming = new Student();

        System.out.println(ming.age);
        System.out.println(ming.score);
        System.out.println(Student.age);//静态属性可以通过 类.属性  直接调用
        //System.out.println(Student.score);  编译出错
        
        //非静态方法的使用,必须new 一个对象出来
        ming.run();   
        //Student.run(); 编译出错
        new Student().run();

        Student.go();
        go();               //静态方法可以直接调用,或者用 类.方法  调用

    }
}

代码块

public class Rubbit {
    {
        //匿名代码块
        //可以用来赋初值
        System.out.println("匿名代码块");
    }
    static {
        //静态代码块
        //最先执行,且只执行一次
        System.out.println("静态代码块");
    }

    public Rubbit() {
        System.out.println("构造方法");
    }

    public static void main(String[] args) {
        Rubbit r = new Rubbit();
        System.out.println("==================");
        Rubbit amiya =  new Rubbit();

    }
}

/*
静态代码块
匿名代码块
构造方法
==================
匿名代码块
构造方法
*/

静态导入包

我们使用random()的时候

得这么写

Math.random();

如果想直接写random()的话,需要静态导入包

import  static java.lang.Math.random;

坚持住,今天做的,虽然辛苦,可这是我送给未来的礼物

img

抽象类和接口

欢迎来到抽象类

  • abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。
  • 抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。
  • 抽象类,不能通过使用new关键字来创建对象,它是用来让子类继承的。
  • 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
  • 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。

看弹幕说:比如你弄一个人物抽象类,有抽象的身高体重,容貌,然后不断弄子类继承,变成新人物,身高,体重,容貌你自己定,还可以加点别的东西。有点像求职模板,空白的自己往里填,不像的地方是可以自己往里加其他东西。

public abstract class Action {
    //abstract ,抽象方法,只有方法名字,没有方法的实现。
    public abstract void doSomething();
    //不能new抽象类,只能靠子类去实现它
    //抽象类中可以有普通方法
    //但抽象方法必须在抽象类中

}

//抽象类的所有方法,继承了它的子类,都必须要实现它的方法,除非它的子类也是
//抽象类,那就用子子类来实现
public class A extends Action{
    @Override
    public void doSomething() {

    }
}

欢迎来到接口

(听弹幕说:接口的默认和静态方法没说,等我看看书,以后再补吧)

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

理解

  • 接口就是规范,定义的是一组规则,体现了现实世界中”如果你是…则必须能…”的思想。如果你是天使,则必须能飞。如果你是汽车,则必须能跑。如果你勇者,则必须扒出圣剑,打败魔王;如果你是程序员,则必须会编程。
  • 接口的本质是标准,就像我们人间的法律一样。制定好后大家都遵守。
  • 面向对象的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么我们讨论设计模式都只针对具备了抽象能力的语言(比如c++、java、c等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。
  • 声明类的关键字是class,声明接口的关键字是interface

作用

  1. 约束--->标准
  2. 定义一些方法,让不同的人实现
  3. public abstract 方法
  4. public static final 常量
  5. 接口不能被实例化,接口中没有构造方法
  6. implements可以实现多个接口
  7. 实现了接口的类,必须要重写接口中的方法
public interface UserService {
    //接口中的所有方法的定义其实都是抽象的,省略了public abstract
    //属性是默认为 常量 public  static final
    //但好像不怎么用属性
    public  static final int age = 99;
    void add(String name);
    void delete(String name);
    void change(String name);
    void get(String name);
}

public interface TimeService {
    void timer();
}

//类可以实现接口  implements 接口
//实现了接口的类,就需要重写接口中的方法。
//多继承,利用接口实现多继承
public class Servicelmpl implements UserService,TimeService{
    //快捷方式  alt + insert 选择implement Mthods
    @Override
    public void add(String name) {

    }

    @Override
    public void delete(String name) {

    }

    @Override
    public void change(String name) {

    }

    @Override
    public void get(String name) {

    }
    @Override
    public void timer(){

    }
}

内部类

内部类(此处仅作了解)

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

成员内部类、静态内部类、局部内部类、匿名内部类

成员内部类

public class Outer {
    private  int id;
    public void out(){
        System.out.println("这是外部类的方法");
    }
    public class Inner{
        public void in(){
            System.out.println("这是内部类的方法");
            Outer.this.out();
            //内部类可以通过  外部类类名.this.外部类方法,调用外部方法
        }
        public void getID(){
            //内部类可以调用外部类的属性
            System.out.println(id);
        }
    }
}


public class HI {
    public static void main(String[] args) {
        Outer o = new Outer();
        //通过这个外部类来实例化内部类
        Outer.Inner i = o.new Inner();
        i.in();
        i.getID();
    }


}

静态内部类

//内部类可以访问外部static属性,但static的内部类不能访问非静态的外部属性
//同时,这边没办法弄内部类对象了,以后再说,浅浅的了解一下
public class Outer {
    private  static int id;
    public void out(){
        System.out.println("这是外部类的方法");
    }
    public static class Inner{
        public void in(){
            System.out.println("这是内部类的方法");

        }
        public void getID(){
          
            System.out.println(id);
        }
    }
}

局部内部类

public class Outer{
    public void methods(){
        
        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("eat an apple");
    }
}
interface UserService{
    void hello();
}

标签:Java,子类,void,System,面向对象,println,public,out
From: https://www.cnblogs.com/tiangong/p/16731970.html

相关文章