欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

面向对象的三大特征和基本语法

程序员文章站 2022-03-03 10:41:29
面向对象(二)一、面向对象三大特征之一:封装1.简述封装(Encapsulation)是面向对象方法的重要原则,就是把对象的属性和操作(或服务)结合为一个独立的整体,并尽可能隐藏对象的内部实现细节(更直白的说是实现高内聚低耦合)访问元素的权限public : 它是可以在全局范围(同一个包或者不同的包)里访问protected : 它能够在同一个包可以访问,但不同的包,只有继承关系,才能访问default(缺省): 只能在同一个包才可以访问private : 只能在本类里...

面向对象(二)

一、面向对象三大特征之一:封装

1.简述

  • 封装(Encapsulation)是面向对象方法的重要原则,就是把对象的属性和操作(或服务)结合为一个独立的整体,并尽可能隐藏对象的内部实现细节(更直白的说是实现高内聚低耦合

  • 访问元素的权限

    • public : 它是可以在全局范围(同一个包或者不同的包)里访问
    • protected : 它能够在同一个包可以访问,但不同的包,只有继承关系,才能访问
    • default(缺省): 只能在同一个包才可以访问
    • private : 只能在本类里面才能访问
  • 案例
    面向对象的三大特征和基本语法

  • 输出的结果

    5 women nojob

  • 当父类属性(成员变量)是私有的 我们就需要借助get和set 方法(才能外部的类调用)

    package inher.home.cn; public class ManKind { //成员变量是私有的 private int sex; private int salary; public int getSex() { return sex; } public void setSex(int sex) { this.sex = sex; } public int getSalary() { return salary; } public void setSalary(int salary) { this.salary = salary; } public void manOrWoman() { if (sex == 1) { System.out.println("man"); } else if (sex == 0) { System.out.println("women"); } } public void employeed() { if (salary == 0) { System.out.println("no job"); } else if (sex != 0) { System.out.println("job"); } } } 
    package inher.home.cn; public class Kids extends ManKind { int yearsOld; public void printAge() { System.out.println(yearsOld); } public static void main(String[] args) { Kids someKid = new Kids(); someKid.yearsOld = 5; someKid.setSex(0); someKid.setSalary(0); someKid.printAge(); someKid.manOrWoman(); someKid.employeed(); } } 
    • 输出的结果

      5 women nojob

二、面向对象三大特征之二:继承

1、为什么要有继承

  • 多个类中存在 相同属性和行为 时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。

  • 父类

    • 将相同的属性及行为抽取到单独类里面,此类称为父类
  • 子类

    • 多个类无需再定义这属性及行为,只要继承父类即可,此类称为子类
  • 子类与父类是什么关系

    • 子类是父类的具体的体现
    • 例如:水果是父类、 苹果是子类,也就是说苹果是水果的一种
    • 子类有多个,父类只有一个

2、语法

public class 子类 extends 父类{ //里面是实现子类的方法 } 
  • 举例

    • 定义一个父类:类名Person

    • 定义一个子类: 分别Student、Waiter、Teacher、Conumser

    • 代码如下

      package demo.cn.com; class Person { String name; int id; int age; public void info() { System.out.println("name=" + name + " id=" + id + "
                      age = "+age); } } class Waiter extends Person { } class Student extends Person { } class Teacher extends Person { } class Consumer extends Person { } public class MainTest { public static void main(String[] args) { Waiter t1 = new Waiter(); t1.name = "张三"; t1.age = 30; t1.id = 1; t1.info(); } } 

3、继承的特征

a、子类具有继承父类资源
  • 如果父类的资源配置private的访问权限,子类无法使用
  • 如果父类的资源配置缺省的访问权限,不同的包的子类无法使用,同一
    个包的子类可以访问
b、单继承性
  • 父类只有一个,但子类可以有多个
    面向对象的三大特征和基本语法
c、 所有的类最终都会继承Object
public class MainTest { public static void main(String[] args) { Waiter t1 = new Waiter(); t1.name = "张三"; t1.age = 30; t1.id = 1; t1.info(); //为什么可以直接调用toString,原因是Object类是所有类的 // 最终继承父类,toString就是在Object类定义,子类可以继承下来使用 String str = t1.toString();//为什么可以调用toString方法 System.out.println(str); } } 

4、方法的重写

a、概述
  • 在子类中可以根据需要对从父类中继承来的方法进行改造,也称为方法
    的重置、覆盖。在程序执行时,子类的方法将覆盖父类的方法。

b、不允许方法的重写

  • static:他是属于类
  • final:常量池
  • 父类是private :私有方法(子类重写不了)
c、重写方法的规则
  • 修饰符的作用范围大小排序:public>protected>缺省>private

  • “两同一小一大”

    • 两同:方法名相同,参数列表一致

    • 一小:重写方法的返回值数据类型<= 被重写的方法的返回值数据类型

      • 返回值数据类型是指子类与父类的范围
    • 一大:重写方法的访问权限符范围>=被重写方法的访问权限符范围
      public/protected/缺省 (重写方法) 缺省(被重写方法)
      public/protected 重写方法 protected(被重写方法)
      public 重写方法 public(被重写方法)
      不受重写规则的约束 private

    • 重写:那么大家都静态方法,那么都是非静态方法

  • 案例

    class Animal { //被重写的方法 public String eat() { System.out.println("animal eatting"); return "100"; } } class Cat extends Animal { //重写方法 //两同:方法名相同、参数列表相同 public String eat() { System.out.println("cat eatting thing"); return "100"; } } public class MainTest { public static void main(String[] args) { Cat t = new Cat(); t.eat(); } } 

三、Super关键字用法

1、概述

  • 通过super关键字,可以在子类访问父类的资源(属性/行为方法)

    • 可以在本类调用父类属性
    • 可以在本类调用父类行为方法
    • 可以在本类调用父类构造器

    super的注意点:

    • super调用父类的构造方法,必须在构造方法的第一个
    • super必须只能在出现在子类的方法或者构造方法中
    • super和this不能同时调用构造方法

2、实例

class Person { protected String name = "张三"; protected int age; public String getInfo() { return "Name: " + name + "\nage: " + age; } } class Student extends Person { protected String name = "李四"; public String getInfo() { //return name; return super.name; } public String getSchool() { String info = super.getInfo(); return info + "  school"; } } public class TestStudent { public static void main(String[] args) { Student t1 = new Student(); System.out.println(t1.getInfo()); System.out.println(t1.getSchool()); } } 

四、调用父类构造器

1、概述

  • 当创建一个类的对象时,首先先调用父类构造器,再到子类的构造器

    • 原因:当父类的构造器没有写什么构造方法时系统默认执行构造器(指是无参构造) 就是调用super()

2、实例

class A { public A() { System.out.println("A"); } } class B extends A { public B(String name) { System.out.println("B"); } } class C extends B { public C() { //隐藏一段代码 super("gec"); System.out.println("C"); } } public class MainTest { public static void main(String[] args) { C c = new C(); } } 

输出结果是 A B C

五、面向对象三大特征之三:多态

1、概述

  • 针对不同的类,对同一个行为能作为不同的响应状态
  • 不同的类:继承关系/实现关系
  • 同一个行为:行为方法

2、多态的体现

  • 产生多态行为要有俩个条件:

    • ①运行时的数据类型与编译时的数据类型不一致 ② 要有方法重写 ③要有继承关系
  • Java引用变量有两个类型:编译时类型(由声明该变量时使用的类型决定)和运行时类型(由实际赋给该变量的对象决定)。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定(左编译右运行
    面向对象的三大特征和基本语法

  • 编译时的数据类型:当程序编译后,此数据类型就确定下来

  • 运行时的数据类型:当程序运行时,此数据类型才确定下来

3、编译时多态

  • 方法重载都是编译时多态。根据实际参数的数据类型、个数和次序,Java在编译时能够确定执行重载方法中的哪一个。
  • 方法覆盖表现出两种多态性,当对象引用本类实例时,为编译时多态
package demo.cn.com; class Fruit { } class Apple extends Fruit { } class Demo { public static void main(String[] args) { Fruit fruit = new Fruit(); //对象引用本类实例 Apple t = new Apple(); //编译时多态 Fruit fruit1 = new Apple();//运行时多态 } } 

4、多态机制

  • 本质

    • 能够根据运行时的数据类型,在运行时刻,判断具体调用那个行为方法
      ①多态机制是针对 行为方法 起作用 ②对属性不起作用

      package demo.cn.com; class ParentCls { public int a = 10; public void info() { System.out.println("parent cls info"); } } class SubCls extends ParentCls { public int a = 20; public void info() { System.out.println("sub cls info"); } } class Asia { public String name = "亚洲人"; public void info() { System.out.println("我是亚洲人"); } } class Chinese extends Asia { public String name = "中国人"; public void info() { System.out.println("我是中国人"); } } public class Demo { public static void main(String[] args) { //SubCls t1=new SubCls(); //编译时的数据是ParentCls,先调用父类方法,运行时数据是在对父类方法进行重写 ParentCls t1 = new SubCls(); //1、编译时的数据类型与运行时的类型不一致 //2、存在方法重写 //启动“多态”机制 System.out.println(t1.a); //打印输出: 10 (调用父类属性值) t1.info(); //打印输出:sub cls info Asia r = new Chinese(); Chinese r2 = new Chinese(); r.info();//打印输出“我是中国人” System.out.println(r.name);//输出亚洲人 Chinese r3 = new Asia(); // error 这个会报错  // 为什么会报错,就这么说 Chinese子类是继承父类的, // 就不能(小的包含大的)只有大的包含小的吧 } } 

5、多态的应用实例

  • 父类作为方法形参,子类的引用变量作为实参,在调用运行时刻,
    根据实现的实参子类方法调用

面向对象的三大特征和基本语法

6.多态总结

  • 多态机制启动的条件
  • 编译时的数据类型与运行时的数据类型不一致,但它们之间存在继承/实现关系
  • 存在“重写方法”
  • 多态机制只作用“行为方法”,针对成员变量不起作用
  • 多态机制作用:增强代码的兼容性

六、instanceof 操作符

1、简介

  • 可以通过此操作符,判断子类是否属于父类,如果属于,则返回true,
    否则返回false

2、作用

  • 强制类型转换之前的判断

    举例

    package demo.cn.com; class A { public int c = 10; } class B extends A { public int c = 20; } public class MainTest { public static void info(A a) { //强制转换成B类型,明确告诉给jvm,我就是一个B类对象 //隐藏一个程序异常(Exception) if (a instanceof B) { int c = ((B) a).c; System.out.println(c); } } public static void main(String[] args) { //创建B对象 B b = new B(); A a = new A(); info(b); System.out.println("hello" instanceof String); System.out.println("hello" instanceof Object); System.out.println(b instanceof B); System.out.println(b instanceof A); System.out.println(a instanceof B); } } 

    案例二、

    新建一个父类Person 俩个子类(Student、Teacher)

    面向对象的三大特征和基本语法

第一个报错的原因:Person 跟 String 都是object类下的,但是他们是属于同一个段位的,也没有继承关系
第二个报错的原因:student跟teacher 都是子类,不存在继承关系;

第三个报错原因:student跟String 存在大小关系,但是不存在继承关系

输出的答案 true true true false false ---------------------- true true true false ------------------------- true true true 

七、强制类型转换

  • 明确告诉给jvm,是什么数据类型,其实也是判断是否存在继承以及父子关系
if(变量 instanceof 数据类型){ ((数据类型)变量).属性/行为 } 
public static void info(A a){ //强制转换成B类型,明确告诉给jvm,我就是一个B类对象 //隐藏一个程序异常(Exception) if(a instanceof B){ int c=((B)a).c; System.out.println(c); } } 
  • 案例

    package demo.cn.com; public class Demo { public static void printInfo(Object o) { //判断此引用变量是否属于String类型 if (o instanceof String) { //强制类型转换成String类型 String msg = (String) o; System.out.println(msg); } } public static void main(String[] args) { printInfo("helloworld"); printInfo(new MainTest()); } } 

八、初始化块

  • 目的是:对类跟对象进行初始化
  • 修饰符:static/缺省
1、初始化块触发的条件
  • 针对非静态初始化块:当创建对象(new一个对象)会触发,它触发时
    间比构造器还早

  • 针对静态初始化块:当类加载到内存,就会触发,只会加载一次

    package day20.com.cn.demo; class Student{ { System.out.println("hello world"); } static { System.out.println("hi hello world"); } } public class DemoTest { public static void main(String[] args) { new Student(); System.out.println("--------------"); new Student(); } } 

    输出的结果
    hi hello world
    hello world
    hello world

2、初始化块访问成员变量
  • 非静态初始化块是否可以直接访问成员变量?
    • 非静态初始化块它是可以直接访问成员变量,但跟它的摆放位置有
      关系,如果非静态初始化块它是放在成员变量之后,则可以直接访
      问,否则不能直接访问,如果要强制访问此变量,则必须添加this
      关键字,此时变量值为未初始化数据值
  • 静态初始化块是否可以访问静态变量?
    • 静态初始化块它是可以直接访问类变量,但跟它的摆放位置有关
      系,如果静态初始化块它是放在类变量之后,则可以直接访问,否
      则不能直接访问,如果要强制访问此类变量,则必须添加类.类变
      量,此变量值为未初始化值数据值
      面向对象的三大特征和基本语法
3、静态代码块与普通代码块的执行顺序
  • 静态代码块>普通代码块 >构造方法(一般情况)

  • ②当在父类和子类中:父类static静态代码块>子类static静态代码块>父类的普通代码块>父类构造方法>子类的普通代码块>子类构造方法

  • 案例一

    package staticTest.demo.cn; import java.util.HashMap; class X { static Y b = new Y(); X() { System.out.print("X"); } { System.out.print("A"); } static { System.out.print("A++"); } } class Y { Y() { System.out.print("Y"); } { System.out.print("B"); } static { System.out.print("B++"); } } public class MainTest extends X { static Y y = new Y(); MainTest() { System.out.print("Z"); } { System.out.print("C"); } static { System.out.print("C++"); } public static void main(String[] args) { /*创建MainTest对象的执行步骤:
            1、父类的成员变量初始化(有静态的话,静态优先)
            2、父类的构造器
            3、本类的成员变量初始化
            4、本类的构造器*/ new MainTest(); System.out.println("\n------"); //        new MainTest(); } } 

    输出结果:

面向对象的三大特征和基本语法

  • 案例二

    根据上面的代码(不修改)我在添加new MainTest();
    面向对象的三大特征和基本语法

为什么在次运行这个对象,值就不同了

原因是:静态变量只能运行一次,再次运行时,静态变量就不会在执行了

九、final关键字

  • 在Java中声明类、变量和方法时,可使用关键字final来修饰,表示“最终”。(当修饰类时是无法继承的)

  • 当定义变量的是用final 修饰时候,第二次赋值的值对final的值是没有影响的

  • final修饰的成员变量:①直接赋值 ②初始化块

  • final修饰的静态成员,可以在什么位置赋值:直接赋值、静态初始化块

    package day20.com.cn.homework;
    
    class Student {
        int age = 10;
    }
    
    class FinalTest {
        public static void main(String[] args) {
    
            int x = 10;
            x = 100;
            System.out.println(x);
            final int y=100;
    //        y = 100;
            System.out.println(y);
            System.out.println("--------------");
    
            //局部变量是引用数据类型
            Student s = new Student();
            System.out.println(s.age);
            s.age = 100;
            System.out.println(s.age);
            System.out.println("--------------");
    
            final Student ss = new Student();
            System.out.println(ss.age);
            ss.age = 100;
            System.out.println(ss.age);
    //        ss = new Student();
        }
    } 

十、抽象类

  • 抽象类特点 :抽象类不能实例化
  • 只要有抽象方法的类,此类肯定是抽象类
  • 抽象方法:没有方法体的方法,称为抽象方法
  • 抽象类不一定有抽象方法
  • 抽象类也有自身的成员变量、构造器、行为方法
  • 只要子类继承于抽象类,此子类必须重写抽象类的抽象方法
  • 父类是抽象类,子类也是用抽象类,那么子子类
abstract class A{ public abstract void info(); //抽象方法 } public class MainTest{ public static void main(String[]args){ //抽象类不能实例化 //A a=new A(); } } 
abstract class A { private int a = 100; public A() { } //抽象方法 abstract void info(); } abstract class B extends A { /*
      public void info()
    {
     System.out.println("B info");  //这个方法就不需要重写
  }*/ abstract void info2(); } class C extends B { public void info() { } public void info2() { } } public class MainTest { public static void main(String[] args) { //抽象类不能实例化 //A a=new A(); //B b=new B(); C c = new C(); } } 

十一、模板设计模式

  • 抽象类体现的就是一种模板模式的设计,抽象类作为多个子类的通用模
    板,子类在抽象类的基础上进行扩展、改造,但子类总体上会保留抽象
    类的行为方式。
abstract class Template { //定义一个方法,此方法实现模板功能 //1、记录调用方法之前的当前时间点 //2、执行方法 //3、记录调用方法之后的当前时间点 //4、执行方法之后的当前时间点-记录调用方法之前的当前时间public final void getTime() { //记录调用方法之前的当前时间点 long start = System.currentTimeMillis(); doMethod(); //记录调用方法之后的当前时间点 long end = System.currentTimeMillis(); //执行方法之后的当前时间点-记录调用方法之前的当前时 间点
        System.out.println("执行时间是:" + (end - start)); } public abstract void doMethod(); } class A extends Template { public void doMethod() { for (int i = 0; i < 20; i++) { System.out.println("a do method i=" + i); try { //耗时1秒钟 Thread.sleep(1000); } catch (Exception e) { } } } } class B extends Template { public void doMethod() { for (int i = 0; i < 5; i++) { System.out.println("a do method i=" + i); try { //耗时1秒钟 Thread.sleep(1000); } catch (Exception e) { } } } } public class MainTest { public static void main(String[] args) { /*
A a=new A();
a.getTime();
*/ B b = new B(); b.getTime(); } } 

十二、接口

  • 从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方
    法的定义(抽象方法),而没有变量和方法的实现。
修饰符 interface 接口名{ //常量![在这里插入图片描述](https://img-blog.csdnimg.cn/2020080909522422.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzYwMDg4Mw==,size_16,color_FFFFFF,t_70) //抽象方法 } 
  • 修饰符
    针对访问权限:
    public/default(缺省)
  • 常量
    如果在接口定义一个变量,此变量其实常量(final static 省
    略)
  • 抽象方法的默认访问权限:public
  • 如何定义
/*
定义一个接口
*/ interface Runner { //抽象方法,默认的访问权限:public void start(); void run(); void stop(); //final static int a=100; int a = 100; } class Person implements Runner { //重写: //规则: //两同、一小、一大 public void start() { System.out.println("perosn start"); } public void run() { System.out.println("perosn run"); } public void stop() { System.out.println("perosn stop"); } } public class MainTest { public static void main(String[] args) { Runner.a = 200; } } 
1、接口的特点
  • 接口也是不能实例化
  • 接口可以多实现
  • 实现类实现此接口,此实现类需要重写接口的抽象方法
  • 接口支持多态
  • 当使用default修饰时,不用必需实现该抽象方法,且用这个修饰时,只是一个方法体了
/*
定义一个接口
*/ interface Runner { //抽象方法,默认的访问权限:public void start(); void run(); void stop(); //final static int a=100; int a = 100; } interface IFly { void fly(); } class Person implements Runner, IFly { //重写: //规则: //两同、一小、一大 public void start() { System.out.println("perosn start"); } public void run() { System.out.println("perosn run"); } public void stop() { System.out.println("perosn stop"); } public void fly() { System.out.println("perosn fly"); } } public class MainTest { public static void main(String[] args) { //new Runner(); IFly f = new Person(); f.fly(); ((Person) f).run(); } } 

本文地址:https://blog.csdn.net/weixin_43600883/article/details/107889596

相关标签: java