关于java:乐字节2020最新面向对象深入2

15次阅读

共计 9050 个字符,预计需要花费 23 分钟才能阅读完成。

java13 面向对象深刻 2

纲要

package 与 import

package

概述

package 存在的意义是 避免命名抵触 造成应用不便。

package 相似一个文件夹,文件夹内有各种文件。package 与 package 的从属关系用“.”连贯,相似父文件夹中的子文件夹。比如说 java.lang.String 就是 java 文件夹中的 lang 文件夹中的 String 文件。java.io.InputStream 则是 java 文件夹中的 io 文件夹中的 InputStream 文件。

同一个文件夹内无奈存在同名的文件,而不同名的文件夹里容许存在同名文件,因而不同文件夹(即不同 package 中容许呈现雷同 class 名)。

<font color=’red’>为了便于管理大型软件系统中数目泛滥的类,解决类的命名抵触问题,Java 引入包 (package) 机制,提供类的多重类命名空间。 </font>

[外链图片转存失败, 源站可能有防盗链机制, 倡议将图片保留下来间接上传(img-5wfeTncC-1607306803072)(/How-to-Ship-a-Package-Internationally.jpg)]

格局

个别的命名为:<font color=”blue”>公司域名倒写 + 性能名 | 模块名。</font>

package 语句作为 Java 源文件的第一条语句,指明该文件中定义的类所在的包。(若缺省该语句,则指定为无名包)。

package pkg1[.pkg2[.pkg3…]];

例:

package com.java01.test;

Java 编译器把包对应于文件系统的目录治理,package 语句中,用’.’来指明包(目录)的档次,例如应用语句: package com.java01 , 则该文件中所有的类位于.\com\java01 目录下

留神:

  • 不要定义与 jdk 雷同的包,雷同的类,否则会引起很多你感觉莫名其妙的问题
  • 写我的项目时都要加包,不要应用默认包。
  • com.oop 和 com.oop.test,这两个包没有蕴含关系,是两个齐全独立的包。只是逻辑上看起来后者是前者的一部分。

import

如果一个类存在包名,则在其余包下应用该类时,必须应用全额限定名(简称全名或残缺类名,com.java01.MyClass),编译器能力找到该类;也能够应用 import 在文件的结尾引入要应用到的类。

import java.util.Scanner;
import java.io.*; // 含糊匹配以后 io 包下所有类
public class ImportDemo {public static void main(String[] args) {Scanner sc=new Scanner(System.in); // 因为应用 import 关键字导包, 能够应用
        java.util.ArrayList list=new java.util.ArrayList(); // 权限定名
        // 导入汇合 留神: 导入是不要导错包
        // 应用 *, 含糊匹配
        File file=new File("D://test.txt");
        InputStream isInputStream=new FileInputStream(file);
    }
}

不须要应用 import 的类有:

  1. 语言包(java.lang)下的类 (String,System…)
  2. 同包下的类

动态导入:
import 语句不仅能够导入类,还减少了导入静态方法的性能

// 导入动态属性
import static java.lang.Math.PI;
import static java.lang.System.out;
// 导入静态方法
import static java.lang.Math.sin;

public class ImportDemo {public static void main(String[] args) {out.println(PI);
        sin(1.1);
    }
}

总结

  • 如果想将一个类放入包中,在类的源文件首行应用 package
  • 必须保障该类的 class 文件位于正确的目录下
  • 另外的类想拜访的话:

    1. 写全名
    2. 引入

      • 含糊匹配(会将该包下所有用到的类引入进来),会升高编译速度,然而不会影响运行速度
      • 具体类名
      • 动态导入
    3. 同包下的类不须要导入


JDK 中罕用的包简略介绍:

  1. java.lang –语言包:语言中罕用的性能,如:String、Math、System、Integer、Thread…
  2. java.util – 工具包:提供一些实用的工具类,如:容器(List、Set、Map…), 日期类
  3. java.io – 输入输出包:提供操作读取文件的相干类,如:File、InputStream、OutputStrem…
  4. java.net – 网络包:操 作 远 程 资 源 的 类,如:InetSocketAddress、DatagramPacket、ServerSocket…
  5. java.sql – 数据库包:操作 JDBC 的类,Connection、Statement、ResultSet….

垃圾回收机制(gc)

概述

Garbage Collection 垃圾回收机制

每个程序员都遇到过内存溢出的状况,程序运行时,内存空间是无限的,那么如何及时的把不再应用的对象革除将内存释放出来,这就是 GC 要做的事。

说起垃圾回收机制(GC),大部分人都把这项技术当做 Java 语言的伴生产物。事实上,GC 的历史比 Java 长远,早在 1960 年 Lisp 这门语言中就应用了内存动态分配和垃圾回收技术。

[外链图片转存失败, 源站可能有防盗链机制, 倡议将图片保留下来间接上传(img-mUMZh2zb-1607306803077)(1554324687-762w_garbage2.jpg)]

程序员们晓得,jvm 内存构造分为五大区域:程序计数器、虚拟机栈、本地办法栈、堆区、办法区。其中虚拟机栈、本地办法栈与程序计数器这 3 个区域随线程而生、随线程而灭,因而就不须要思考过多内存垃圾回收问题,因为一个办法调用完结或者线程完结时,内存天然就跟随着回收了。

咱们就把重点放在办法区与堆区,这部分内存的调配和回收是动静的,正是垃圾收集器所需关注的局部。

GC 次要做了清理对象,整顿内存的工作。

不同语言下对象空间的开释:

  • 传统的 C /C++ 语言,须要程序员负责回收曾经分配内存。显式回收垃圾回收的毛病:

    1. 程序遗记及时回收,从而导致内存泄露,升高零碎性能。
    2. 程序谬误回收程序外围类库的内存,导致系统解体。
  • Java 语言不须要程序员间接管制内存回收,是由 JRE 在后盾主动回收不再应用的内存,称为垃圾

    回收机制(Garbage Collection)。

    1. 能够进步编程效率。
    2. 爱护程序的完整性。
    3. 其开销影响性能。Java 虚拟机必须跟踪程序中有用的对象,确定哪些是无用的。

垃圾回收机制关键点:

  • 垃圾回收机制只回收 JVM 堆内存里的对象空间。
  • 对其余物理连贯,比方数据库连贯、输出流输入流、Socket 连贯无能为力
  • 当初的 JVM 有多种垃圾回收实现算法,体现各异。
  • 垃圾回收产生具备不可预知性,程序无奈准确管制垃圾回收机制执行。
  • 能够将对象的援用变量设置为 null,暗示垃圾回收机制能够回收该对象。
  • 程序员能够通过 System.gc()或者 Runtime.getRuntime().gc()来告诉零碎进行垃圾回收,会有一些成果,然而零碎是否进行垃圾回收仍然不确定。
  • 垃圾回收机制回收任何对象之前,总会先调用它的 finalize 办法(如果笼罩该办法,让一个新的援用变量从新援用该对象,则会从新激活对象)。
  • 永远不要被动调用某个对象的 finalize 办法,应该交给垃圾回收机制调用。

block 与 debug

block

块{}, 在 java 中自成作用域,能够分为

动态代码块 结构代码块 一般语句块 同步代码块
申明地位 类中, 办法外 类中, 办法外 办法中 fynchronized(){}
作用 整个类进行某些初始化操作(动态成员属性赋值 …) 结构代码块是为对象初始化操作(为动态或非动态成员属性赋值 …) 申明一些长期变量等.. 管制并发
执行机会 类第一次加载时, 只执行一次, 如果多个动态块, 从上倒下一次执行 创建对象时, 执行结构器代码之前执行, 如有多个, 从上倒下一次执行 追随办法执行 跟对办法执行

留神:

  • 类第一次被载入时先执行 static 代码块;类屡次载入时,static 代码块只执行一次;static 块常常用来进行 static 变量的初始化。
  • 是在类初始化时执行,不是在创建对象时执行。
  • 动态初始化块中不能拜访非 static 成员。
  • 结构块被被编译到将要执行的结构器代码之前执行

动态块,仅在类的第一次应用时加载。
结构块,先于结构器执行,每创立一个对象执行一次

debug

在学习或开发过程中, 遇到 bug 是防止不了的, 为了可能疾速调试, 能够应用 debug 调试工具。

调试一个 Java 程序非常简单的,次要有设置断点、启动调试、单步执行、完结调试几步。

debug 界面窗口:

[外链图片转存失败, 源站可能有防盗链机制, 倡议将图片保留下来间接上传(img-v0sFdz5F-1607306803082)(/20170212112040869)]

1)设置断点

[外链图片转存失败, 源站可能有防盗链机制, 倡议将图片保留下来间接上传(img-B38if1WY-1607306803085)(/20170212133523789.png)]

2)启动调试

Eclipse 提供几种形式来启动程序 (Launch) 的调试,别离是通过菜单(Run –> Debug)、图标(“绿色臭虫”)、右键 ->Debug As。

[外链图片转存失败, 源站可能有防盗链机制, 倡议将图片保留下来间接上传(img-hnOKVyTw-1607306803088)(/20170212133853247)]

弹出提醒,须要切换到调试(Debug)工作区,勾选“Remember my decision”,记住抉择,则下次不再提醒,而后点击【Yes】。

[外链图片转存失败, 源站可能有防盗链机制, 倡议将图片保留下来间接上传(img-MWZ05Nz0-1607306803091)(/20170212133942295)]

3)单步执行

次要应用后面讲过的几个视图进行调试,其中 debug 视图中的几个按钮有快捷键:

Step Return(F7) : 示意退出以后办法,返回到调用层。

Step Over (F6) : 示意运行下一行代码。

Step Into (F5) : 示意进入以后办法。

[外链图片转存失败, 源站可能有防盗链机制, 倡议将图片保留下来间接上传(img-eGaWwKUV-1607306803092)(/1581682185893.png)]

4)完结调试

通过 Terminate 命令终止对本地程序的调试。

面向对象 - 继承性

继承

“树上一只鸟树下两只兔子,请问几种动物 , 请问几种生物?”这外面就存在了继承的概念。

[外链图片转存失败, 源站可能有防盗链机制, 倡议将图片保留下来间接上传(img-jbZKv6BO-1607306803094)(/1581683059636.png)]

继承:子承父业

继承的实质在于形象。类是对对象的形象,继承是对某一批类的形象,从而实现对事实世界更好的建模。

继承的作用 : 应用继承能够进步代码的复用性。

如何应用继承:

父类 | 超类 | 基类: 依据一些列子类形象, 抽取像的局部, 定义在父类中

子类 | 派生类: 子类继承父类, 有权应用父类中的内容, 能够定义子类新增内容, 所以说子类是父类的连续 + 扩大

extends 关键字的意思是“扩大”。子类是父类的扩大。

java 中应用 <font color=”red”>extends </font> 关键字实现类的继承机制,语法规定:

<modifier> class <name> [extends <superclass>]{} 
// 父类
class Person{
    public String name;
    public int age;
    
    public void sleep(){System.out.println("劳动");
    }
}
// 子类
// 老师类
class Teacher extends Person{
    public String subject;
    
    public Teacher() {}
    
    public void teach(){System.out.println("传授常识");
    }
    
}

// 学生类
class Student extends Person{
    public String school;
    
    public Student() {}
    
    public void study(){System.out.println("在常识的陆地畅游!");
    }
}

留神:

  • 子类继承父类的成员变量和成员办法,但不继承父类的构造方法
  • java 中只有单继承,没有像 c ++ 那样的多继承。多继承会引起凌乱,使得继承链过于简单,零碎难于保护。就像咱们事实中,如果你有多个父母亲,那是一个如许凌乱的世界啊。多继承,就是为了实现代码的复用性,却引入了复杂性,使得零碎类之间的关系凌乱。
  • java 中的多继承,能够通过接口来实现
  • 如果定义一个类时,没有调用 extends,则它的父类是:java.lang.Object。

继承的特点:

长处:

  • 通过继承能够简化类的定义,实现代码的重用 | 进步代码复用性
  • 能够更好的扩大程序
  • 子类一旦继承父类, 能够有权应用父类中的成员, 也能够扩大定义子类独有内容
  • java 是单继承继承, 实现简略

毛病:

  • 子类与父类之间严密耦合(耦合度高),子类依赖于父类的实现,子类不足独立性。
  • 不便于前期保护
  • 单继承一个子类只能有一个父类, 不够灵便, 不便于前期保护

super 关键字

super

super 是指向父类的援用。

super 能够在子类结构器中调用父类某个结构器

如果构造方法没有显示地调用父类的构造方法,那么编译器会主动为它加上一个默认的 super()办法调用。如果父类由没有默认的无参构造方法,编译器就会报错,super()语句必须是构造方法的第一个子句。

super 能够用来区分子父类中同名成员

如果不存在同名问题, 能够间接在子类中调用父类内容,super 默认省略

如果存在同名问题, 在子类中调用同名成员, 默认 this. 恒源 调用以后子类同名成员, 先要调用父类同名成员, 必须定义为 super. 成员

// 父类
public class Animal {
    int eye = 2;
    public Animal(){super();
        System.out.println("动物");
    }
    
    public void run(){System.out.println("动物有不同走路形式");
    }
    
    public static void main(String[] args) {Bird b = new Bird();
        b.run();}
}
// 子类
class Bird extends Animal{public Bird(){super();
        System.out.println("鸟类");
    }

    public void run() {super.run(); // 通过 super 能够用父类办法和属性
        System.out.println("鸟是飞飞飞飞飞飞");
        System.out.println("鸟类有"+super.eye+"只眼睛");
    }
   
}

Bird–> Animal –> Object 图形剖析如下
[外链图片转存失败, 源站可能有防盗链机制, 倡议将图片保留下来间接上传(img-uUJguEhi-1607306803096)(/1026930-20180501170153513-1275315563.png)]

构造方法调用程序:

  • 依据 super 的阐明,构造方法第一句 总是:super(…)来调用父类对应的构造方法。
  • 先向上追溯到 Object,而后再顺次向下执行类的初始化块和构造方法,直到以后子类为止。

this 和 super 之间的区别

相同点:

  1. this 和 super 都能用来调动其余共结构器, 都要在首行呈现
  2. this 和 super 都能够用来辨别同名问题, 不辨别同名时候能够省略
  3. this 和 super 都指的是对象,所以,均不能够在 static 环境中应用。包含:static 变量,static 办法,static 语句

块。

不同点:

  1. this(参数)结构器第一行调用本类中其余结构器,super(参数)结构器第一行调用父类中某个结构器
  2. this 用来辨别成员和部分同名问题,super 用来区分子父类中同名问题

留神:

  • this 和 super 不能同时呈现在一个构造函数外面,因为 this 必然会调用其它的构造函数,其它的构造函数必然也会有 super 语句的存在,所以在同一个构造函数外面有雷同的语句,就失去了语句的意义,编译器也不会过。
  • 从实质上讲,this 是一个指向本对象的指针, 然而 super 是一个 Java 关键字

重写与 final 关键字

重写 Override

父类的性能实现不满足子类的要求,能够在子类中按需改写, 这就是办法的重写。

实现重写的三个条件:

  • 不同的两个类
  • 继承关系 | 实现关系
  • 办法签名雷同

@Override: 注解, 强制查看是否为重写办法

留神:

  • 子类重写的办法会对父类的办法进行屏蔽。
  • 当子类对象调用时, 会调用子类中重写的办法, 子类没有找父类。
public class OverrideTest {public static void main(String[] args) {Sicong sicong=new Sicong();
        sicong.getMoney(); // 调用子类中重写办法}
}
// 父类
class Jianlin{public void getMoney(){System.out.println("先定一个小指标, 赚他个一个亿");
    }
}
// 子类
class Sicong extends Jianlin{
    @Override  // 强制查看是否为重写办法
    public void getMoney(){super.getMoney();// 在父类的原赚钱办法上扩大新性能, 老性能不变
        System.out.println("我意识的人都没我有钱");
    }
}

重写的三个 ”=” :
“==”:办法名、形参列表雷同。

“≤”:抛出的异样类型与返回值类型, 返回值类型如果为根本类型必须雷同,援用数据类型子类小于等于父类。

“≥”:拜访权限,子类大于等于父类。

以下修饰符、润饰的内容不能重写:

  1. private 润饰的办法不能被重写
  2. final 润饰的办法不能被重写
  3. static 润饰的办法不能被重写(子类如果呈现和父类静态方法同名状况, 那么子类中的办法也必须为动态的)

final 关键字

final 示意最终的。

final 能够用来润饰变量,办法,类。

润饰变量:变量一旦被初始化便不可扭转,相当定义了一常量。

final int x=3;
//x=4; 常量不能扭转

润饰办法 : final 办法是在子类中不能被笼罩的办法

final void eat() { …}

润饰类,示意该类不能被继承

final class Person{…}

Object 类

Object 类是所有 Java 类的根基类

如果在类的申明中未应用 extends 关键字指明其基类,则默认基类为 Object 类

[外链图片转存失败, 源站可能有防盗链机制, 倡议将图片保留下来间接上传(img-2mBpmF4p-1607306803099)(/1581686929678.png)]

toString(): 当打印对象的援用时, 默认调用 toString()办法

  • 默认返回: 包名 + 类名 +@+ 哈希码(依据对象的内存地址生成, 惟一不反复)
  • 能够重写, 实现义字符串的模式返回对对象(打印对象所有成员属性的值)
User p1=new User("张三",20);
System.out.println(p1);
// 相当于
System.out.println(p1.toString());

equals: 比拟相等是否相等 **

  • 默认地址比拟(”第一个盒子的比拟”)
  • 重写能够是实现比拟两对象的内容是否统一
 object1.equals(object2) 
 如 : p1.equals(p2)
• 比拟所指对象的内容是否一样, 具体看 equals 的办法重写
 object1 == object2
 如:p1==p2
• 比拟 p1 和 p2 的值即内存地址是否相等,即是否是指向同一对象。

留神: 自定义类须重写 equals(),否则无奈实现比拟其内容

class User{
    String name;
    int age;
    public User() {// TODO Auto-generated constructor stub}
    public User(String name, int age) {super();
        this.name = name;
        this.age = age;
    }
    // 重写 toString
    @Override
    public String toString() {return "User [name=" + name + ", age=" + age + "]";
    }
    // 重写 equals
    @Override
    public boolean equals(Object obj) {if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        User other = (User) obj;
        if (age != other.age)
            return false;
        if (name == null) {if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
}
    super();
    this.name = name;
    this.age = age;
}
// 重写 toString
@Override
public String toString() {return "User [name=" + name + ", age=" + age + "]";
}
// 重写 equals
@Override
public boolean equals(Object obj) {if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    User other = (User) obj;
    if (age != other.age)
        return false;
    if (name == null) {if (other.name != null)
            return false;
    } else if (!name.equals(other.name))
        return false;
    return true;
}

}

正文完
 0