浅显回顾 Java 面向对象的最后方面的知识

今天主要回顾一下 Java 面向对象的最后一部分的知识,算是对面向对象的一个总结了吧!

先来讲两个关键字吧!

1. abstract

如果一个类的所有子类都对这个类中的某个方法做了重写,那么这个时候这个类中的对应方法可以不定义方法体,需要用abstract修饰方法,从而成为一个抽象方法。抽象方法所在的类必须是抽象类

抽象类不能创建对象。 --- 抽象方法一定是抽象类,但抽象类中不一定有抽象方法。

抽象类一定不是最终类,因为最终类不能被继承。

注意:任何一个类都有构造方法

抽象方法没有方法体,一定要被重写。

抽象方法可以定义被 static/final/private 修饰吗? --- 不行

抽象方法中一定不能定义在最终类中。

如果一个类中的抽象方法用的是默认权限,对子类有什么要求? --- 要求父子类要同包

package abstractx;

public class AbstractDemo {

    //不允许被实例化
    //Pet p = new Pet();
    //p.eat();

    //创建的是匿名内部类
    Pet p = new Pet(){

        @Override
        public void eat() {
            // TODO Auto-generated method stub

        }

    };

}

//不想让这个类实例化,就定义一个抽象类
abstract class Animal{}

//抽象类
abstract class Pet{

    //
    public Pet(){}

    //抽象方法,因为长得像方法,但是没有方法体
    public abstract void eat();/*{
        //System.out.println("在吃东西~~~");//有没有方法体都不重要了
    }*/

    public void drink(){
        System.out.println("在喝水中~~~");
    }
}

//子类继承抽象类之后必须重写其中的抽象方法,除非子类也是抽象类
class Cat extends Pet{

    @Override
    public void eat(){
        System.out.println("这只猫在吃土~~~");
    }

}

class Dog extends Pet{

    @Override
    public void eat(){
        System.out.println("这只狗在吃猫~~~");
    }

}

练习:定义一个类表示形状,提供获取周长和面积的方法,然后给这个类提供子类:矩形 - 正方形,椭圆 - 圆形

package abstractx;

public class AbstractExer {
    public static void main(String[] args) {
        Shape f;
        f = new Rectangle(3,4);
        System.out.println(f.getGirth() + "," + f.getArea());
        f = new Oval(4,5);
        System.out.println(f.getGirth() + "," + f.getArea());
    }
}

abstract class Shape{

    public abstract double getGirth();
    public abstract double getArea();
}

//代表矩形
class Rectangle extends Shape{

    double width;
    double height;

    public Rectangle(double width, double height){
        this.width = width;
        this.height = height;
    }
    @Override
    public double getGirth() {
        return 2 * (width + height);
    }

    @Override
    public double getArea() {
        // TODO Auto-generated method stub
        return width * height;
    }

}

//正方形
class Square extends Rectangle{

    private double width;
    public Square(double width) {
        super(width, width);
    }

}

//椭圆形
class Oval extends Shape{

    private double a;
    private double b;
    public static final double PI = 3.14;

    public Oval(double a, double b){
        this.a = a;
        this.b = b;
    }

    @Override
    public double getGirth() {
        // TODO Auto-generated method stub
        return PI * a * b;
    }

    @Override
    public double getArea() {
        // TODO Auto-generated method stub
        return PI * (a + b);
    }

}

//圆形
class Circle extends Oval{

    private double r;

    public Circle(double r){
        super(r, r);
    }

}

2. interface

接口中定义的都是抽象方法。类和接口之间用的是 implements 关键字来产生关联 --- 实现。类和实现接口之后需要重写接口中所有的抽象方法

接口不允许被实例化,也没有构造方法。

在 Java 中,支持的是类和接口之间的多实现 --- 一个类可以实现多个接口

在 Java 中,支持接口之间的多继承(接口可以继承接口),

在 JDK1.8 中,接口中允许定义实体方法 -- 这个是实体方法必须用 default 修饰

package cn.tedu.interfacex;

import java.io.Serializable;

public class InterfaceDemo {

    public static void main(String[] args) {

        System.out.println(Shape.girth);
        //Shape.girth = 1;//说明是使用final修饰的

        //接口不允许实例化
        //Shape s = new Shape();
    }
}

interface Shape extends Cloneable,Serializable{

    double girth = 0;//默认是用的 static,final

    //public Shape(){}不允许使用

    //接口中的方法默认public abstract修饰
    /*public abstract */double getGirth();
    public abstract double getArea();

}

//利用implements关键字让类和接口产生了联系 --- 实现
//Rectangle实现了 Shape接口
/*class Rectangle implements Shape, Cloneable{

}
*/

interface E{
    void main();
}

/*class B implements E{

    void main() {//报错了,范围不一样

    }

}*/

关于接口的实现中,我们有:

package cn.tedu.interfacex;

public class InterfaceDemo2 {

    public static void main(String[] args) {

        A a = new B1();

        //在 Java 中支持的是类和类之间的单继承
        //所以此时会形成一颗结构树
        //所以比较容易的就能确定两个类之间是否有继承关系
        //因此在进行强制转换的时候
        //会检查要转换的对象的声明类和转换的类型是否有继承关系
        //a对象的声明类型是 A 类,要转换的类型是B1
        //B1继承了A,所以在编译时期就不报错
        //到了运行的时候才会检查对象的实际类型和要转换的类型是否一致
        //运行的时候,发现a的实际类型是 B1,要转换的类型是B1
        //类型一致,允许转换

        B1 b1 = (B1) a;//编译、运行都不会报错

        //a对象的声明类型是 A 类,要转换的类型是B2
        //B2继承了A,所以在编译时期就不报错
        //到了运行的时候,a的实际类型是B1,要转换的类型是B2
        //类型不一致,所以报错 --- ClassCastException

        /*B2 b2 = (B2) a;//编译通过,但是运行会报错
        B2 b3 = (B2) b1;//编译直接不通过
        C c = (C) a;*///编译直接不通过
        //在 Java 中,类和接口之间是多实现,接口和接口之间是继承关系
        //所以构成了一张图状结构 --- 网状结构,
        //不容易确定两个节点之间的关系
        //因此在编译时期为了提高效率放弃检查
        //直到运行时候在确定类型是否是否相同
        D d = (D) a;//编译通过,但是运行报错

    }
}

class A{}

class B1 extends A{}

class B2 extends A{}

class C{}

interface D{}

接着我们谈谈关于内部类方面的知识吧!!

内部类

1. 方法内部类

定义在方法中的类 --- 方法/局部内部类 --- 为了重复使用某段逻辑,并且使这段逻辑只从属于某一个方法使用

package cn.tedu.innerclass;

public class InnerDemo1 {

    public static void main(String[] args) {

        Outer1 outer1 = new Outer1();
        outer1.m();
    }

}

class Outer1{

    int i = 10;

    public void m(){
        System.out.println("Outer~~~");

        //当方法内部类使用所在的方法中的数据的时候,
        //要求这个属性的是一个常量
        //从JDK1.8开始,方法内部类使用到当前方法中的数据的时候,将该数据默认为常量,不能改变
        //常量的隐式声明:
        int j = 5;

        //方法内部类
        //只能在定义它的方法中使用
        //可以使用外部类中的属性何方法
        //如果内部类和外部类存在同名属性或者方法,则使用内部类中定义
        //只能用abstract/final修饰
        //方法内部类可以定义非静态的属性和非静态方法
        //但是不能定义静态变量和静态方法
        //然而定义静态常量
        class Inner1{//不能用static 修饰

            int k = 8;
            static final int x = 7;//会报错,加final变成一个常量

            public void m(){
                System.out.println("Inner~~~");
                i += 5;
                m2();
                //外部类.this.外部类的方法或者属性
                Outer1.this.m2();

                System.out.println(j);
                //j++;//会报错

            }

            public void m2(){
                System.out.println("Inner m2~~~");
            }

        }

        Inner1 i1 = new Inner1();
        i1.m();
    }

    public void m2(){
        System.out.println("m2~~~");
    }

}

2. 成员内部类

Outer2.Inner2 oi2 = new Outer2().new Inner2();

package cn.tedu.innerclass;

public class InnerDemo2 {

    public static void main(String[] args) {

        Outer2 o2 = new Outer2();

        Outer2.Inner2 oi2 = new Outer2().new Inner2();//利用外部类对象创建内部类
        System.out.println(oi2.j);
    }

}

class Outer2{

    int i = 3;

    Inner2 i2 = new Inner2();

    //成员内部类
    //可以使用外部类中的属性和方法
    //可以定义非静态属性和非静态方法
    //但是不能定义静态属性和静态方法
    //然而定义静态常量
    class Inner2{//修饰不受什么限制

        int j = 10;
        static final int k = 8;//也是要加final

        public void m(){
            i += 3;
            Outer2.this.m();//调用外部类中的,不然就是递归了
        }

    }

    public void m(){
        System.out.println("Outer~~~");
    }

}

3. 静态内部类

用 static 修饰的类

Outer3.Inner3 oi3 = new Outer3.Inner3();

package cn.tedu.innerclass;

public class InnerDemo3 {

    public static void main(String[] args) {

        Outer3.Inner3 oi3 = new Outer3.Inner3();
        oi3.m();

    }

}

class Outer3{

    int i = 0;

    //静态内部类
    //只能使用外部类中的静态属性和静态方法
    //静态内部类中可以定义一切的方法和属性,无论静态还是非静态
    static class Inner3{

        int j = 8;
        static int k = 4;

        public void m(){
            //System.out.println(i);//报错
        }

    }

}

4. 匿名内部类

匿名内部类本质上是实现了对应的接口或者是继承了对应的类

任何一个接口都可以存内在匿名内部类形式

一个类只要可以被继承,那么就可以存在匿名内部类形式 --- 最终类不存在匿名内部类的形式

package cn.tedu.innerclass;

public class InnerDeom4 {

    public static void main(String[] args) {

        //匿名内部类
        //a是匿名内部类产生的对象
        //匿名内部类实际上是实现了对应的接口
        A a = new A(){

            @Override
            public void m() {
                System.out.println("running");
            }

        };

        a.m();
        //匿名内部类实际上是继承了对应的类
        B b = new B(){

            @Override
            public void m() {
                System.out.println("running");
            }};
            b.m();

            //C c = new C(){};
    }

}

interface A{

    void m();

}

abstract class B{

    public abstract void m();
}

final class C{}

扩展:类中可以定义类,类中也可以定义接口,接口中也可以定义类,接口中也可以定义接口 --- 如果类中定义了接口或者式接口中定义了接口,那么称之为内部接口 --- 类中定义的接口,以及接口中定义的类和接口默认都是静态的。

谈到这儿,还有个 Lambda 表达式的内容:

package cn.tedu.innerclass;

public class LambdaDemo {

    public static void main(String[] args) {

        //接口中只定义了1个抽象方法
        //可以利用
        /*Calc c = new Calc(){

            @Override
            public double add(double i, double j) {
                // TODO Auto-generated method stub
                return i + j;
            }};*/
        //表示重写Calc中的唯一的一个抽象方法add
        //Lambda表达式只能作用在函数式接口上
        //方法体只有一句,可以省略{}和return 不写
        //唯一的依据方法体的计算结果默认为当前方法的返回值

        //Calc c = (double i, double j) -> i + j;

        //重写的是 Calc 接口中的方法add
        //add方法的参数列表的类型是已知的
        //可以省略参数类型不写
        //函数式编程
        Calc c = (x, y) -> x + y;

        System.out.println(c.add(4.3, 2.5));
    }

}

interface Calc{

    double add(double i, double j);
}

接着,前面打一个小结,接下来进行包的介绍:

声明包用的是 package --- 区分同名类,进行功能的划分

导入包用的是 import --- 导包的作用是用于提示代码从哪儿去找这个类(比如,我们前段时间经常使用的 Scanner、Arrays)

这个类

* 表示导入当前包下的所有的类但是不包括子包下的类

java --- 原生包,提供的一些常用的包,sun 公司自己用的

javax --- 扩展包,后阶段用的比较多

org --- 第三方厂商提供的一些常用的包,sun公司感觉比较好就收过来了

java.lang - 核心/基本包( System  String)  ,包含了 Java 程序运行需要的基本类,在 Java 程序启动的时候,包下的类就已经自动加载到内存中,所以使用的时候可以不用导包

java.awt

java.applet --- JDK 1.9 后大部分类已经被抛弃了

java.util - 工具包

java.math --- 数学运算

java.io ---数据传输

java.net --- 网络通信,后面介绍

java.nio --- 高并发,服务器有关的包,双十一的时候抢购处理这些数据

java.text --- 格式化,超市去买东西,结账系统,8.88,* 3 * 0.88 出现 4 位小数,现实生活中是两位,就用这个包

总结:java.lang 包下的类以及同包类在使用的时候可以不用导包

包就是一个用来声明和导入的,现阶段还没有什么更多的知识介绍,以后遇到了,再介绍吧!!接下来谈谈垃圾分代回收方面的知识:

垃圾分代回收机制

(针对的是堆内存。)

java 中的每种数据类型大小都是确定的,所以所有的内存是由 Java 自己进行分配,意味着内存的管理和回收也是由 JVM 自己进行 --- 在 Java 中一旦产生内存问题导致程序员无法处理。(在 C 和 C++ 中就是自己来定义管理的)理论上在正常情况下 Java 中的堆内存是足够使用的 --- 当堆内存使用的负荷量(堆内存的 70 %,可能有的时候又不一样)超过一定限度的时候,会启动垃圾回收器(Garbage Collector --- GC)进行堆内存的回收释放 ---

C int 只要不超过 4 个字节就行。

int i = 3;   --- 3

int j = i;   --- 1

扩展:eden:from :to = 8:1:1

上图的简介:对象刚创建的时候是先放入新生代中的伊甸园区;如果在伊甸园区经过一次回收依然存在,那么将这个对象挪到幸存区,在幸存区中经过多次回收这个对象依然存在则挪到老生代。在回收的时候先回收新生代,如果新生代回收之后的内存足够使用则不扫描老生代。老生代的扫描频率要低于新生代

发生在新生代的回收 --- 初代回收 minor gc

发生在老生代的回收 --- 完全回收 full gc

(对于双十一,购物完之后就产生和销毁,应该将新生代设置得大一点,方便对象的创建)

扩展:对象创建完成之后会先试图放入新生代;如果新生代经过回收之后也放不开,则直接试图将该对象放入老生代。老生代如果也放不开,则会出现错误 --- OutOfMemoryError.

原文地址:https://www.cnblogs.com/tangdiao/p/9470431.html

时间: 2024-10-08 17:28:04

浅显回顾 Java 面向对象的最后方面的知识的相关文章

java基础知识回顾之面向对象

一 . 抽象类 什么是抽象类?很简单,就是用abstract关键字修饰,并允许包含未实现方法的类. 什么时候定义抽象类?在有些情况下,可能有些方法无法确定要怎么实现,这时就可以定义抽象类,无法实现的方法定义成抽象方法. 抽象类的特性: 1. 不能实例化,即不能创建对象,只能作为父类被继承. 2. 子类继承一个抽象类后,必须实现父类的抽象方法. 3. 抽象类中可以有抽象方法,也可以不包含抽象方法,但如果包含抽象方法,就必须定义成抽象类. public abstract class Shaoe{ p

猫抓老鼠-Java面向对象特点梳理

我们先设计一个猫抓老鼠的小游戏: ⊙猫和老鼠都有名字和体重两种属性,猫有抓老鼠的方法,对应的老鼠则有逃跑的方法. ⊙首先游戏的结果是猫抓住了老鼠或者老鼠逃跑了,对于这两种情况,我们用体重来区分,若猫的体重大于或等于老鼠的体重,则猫可实现抓住老鼠的方法,若猫的体重小于老鼠的体重,则老鼠实现了逃跑的方法. 分析一下,第一步我们需要建立两个类:Cat.Mouse:并且分别声明其各自拥有的方法:  //Cat.java package Testprogramming //打包语句,将Cat类存于Test

Java面向对象----个人参考资料

Java面向对象 :什么是面向对象.类与对象.封装.构造方法.static关键字.继承.抽象类.接口.多态 一.什么是面向对象 1.面向过程思想 面向过程:(PO,Procedure Oriented) 在理解面向对象思想之前,我首先来回顾一下以前C语言中的面向过程思想,面向过程思想强调的是过程(动作),在面向过程的开发中,其实就是面向着具体的每一个步骤和过程,把每一个步骤和过程完成,然而由这些功能方法相互调用,完成需求.面向过程的典型代表语言是:C语言. 2.面向对象思想 面向对象:(OO,

实验二:Java面向对象程序设计

实验二 Java面向对象程序设计 目录 [一.单元测试和TDD](#first) [任务一:实现百分制成绩转成"优.良.中.及格.不及格"五级制成绩的功能](#firstTask) [任务二:以TDD的方式研究学习StringBuffer](#SecondTask) [二.面向对象三要素:封装.继承.多态](#Second) [任务三:使用StarUML对实验二中的代码进行建模](#ThirdTask) [三.设计模式](#third) [任务四:对MyDoc类进行扩充,让其支持Lon

Java面向对象之异常详解

目录 Java面向对象之异常[一] Java面向对象之异常[二] 捕获异常的规则 访问异常信息 异常对方法重写的影响 finally详解 Java面向对象之异常[一] Java面向对象之异常[二] 往期回顾:上一篇我们大致总结了异常的继承体系,说明了Exception和Error两个大类都继承于顶级父类Throwable,又谈到编译时异常与运行时异常的区别,谈到异常的处理方式,以及处理方式中关于捕获方式的几种类型. 本篇承上启下,将从异常的其余部分进行总结,但是毕竟现在处于初学阶段,未必能够体会

Java面向对象编程三大特征 - 多态

Java面向对象编程三大特征 - 多态 本文关键字:Java.面向对象.三大特征.多态多态是面向对象编程的三大特征之一,是面向对象思想的终极体现之一.在理解多态之前需要先掌握继承.重写.父类引用指向子类对象的相关概念,对继承还没有完全明白的同学可进传送门:Java面向对象编程三大特征 - 继承. 一.抽象类 在继承中,我们已经了解了子父类的关系以及如何对子父类进行设计,如果已经存在多个实体类,再去定义父类其实是不断的抽取公共重合部分的过程,如果有需要将会产生多重继承关系.在抽取整理的过程中,除了

2062326 齐力锋 实验四《Java面向对象程序设计Android开发》实验报告

北京电子科技学院(BESTI) 实 验 报 告 课程: 程序设计与数据结构  班级: 1623  姓名: 齐力锋 学号: 20162326 成绩: 指导教师: 娄嘉鹏/王志强 实验日期: 2017年5月26日 实验密级:非密级 预习程度: 优良 实验时间: 2 Hours 仪器组次: 必修/选修: 必修 实验序号: 04 实验名称:Java面向对象程序设计Android开发 实验内容 1.Android Stuidio的安装测试: 参考<Java和Android开发学习指南(第二版)(EPUBI

java面向对象的核心思想

Java面向对象-抽象类与接口 1.Java final关键字的使用 package edu.tongji.fni; /*final关键字 * 1.final关键字在java中被称为完结器,表示最终的意思 * 2.final能声明类.方法.属性: * 使用final声明的类不能被继承 * 使用final声明的方法不能被重写 * 使用final声明的变量变成常量,常量是不可以被修改的 */ class People{ //前面加了final下面的类会报错 public void tell(){ }

JavaSE入门学习21:Java面向对象之接口(interface)(二)

一接口实现的多态 在上一篇博文:JavaSE入门学习20:Java面向对象之接口(interface)(一)中提到了接口的实现存在多态性,那么 这一篇主要就要分析接口实现的多态. 实例一 Test.java源文件代码: public class Test{ public static void main(String[] args){ //实现接口Singer Singer s1 = new Student("Amy"); s1.sing(); s1.sleep(); s1.study