当前位置: 移动技术网 > IT编程>软件设计>面向对象 > 面向对象的三大特征和基本语法

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

2020年08月10日  | 移动技术网IT编程  | 我要评论
面向对象(二)一、面向对象三大特征之一:封装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

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网