美文网首页
java编程思想5-初始化与清理

java编程思想5-初始化与清理

作者: 脏脏包盛 | 来源:发表于2020-01-01 15:34 被阅读0次

    <meta charset="utf-8">

    1 构造器

    不接受任何参数的构造器叫做默认构造器,如果没有编写构造器,则会自动创建无参构造器。如果有构造器,则不会自动创建无参构造器。

    方法覆盖:返回值类型,参数个数,参数类型都必须相同,且权限要大于等于父类权限

    2 方法重载

    方法名相同,形式参数不同。每一个重载的方法都必须有一个独一无二的参数类型列表。

    参数顺序也可以区分方法,但是会使代码难以维护。

    不可以用返回值区分重载方法。重载方法可以有不同的返回值,但是参数列表一定不相同

    void f(){}

    int f(){}

    如果可以上述例子的话,我们调用f() 并不知道调用哪个方法,所以没有办法区分方法。

    涉及基本类型的重载

    1 基本类型能从一个较小的类型自动提升到一个较大的类型,此过程一旦牵涉到重载,可能会造成一些混淆。

    三条规则

    • char byte short int long float double默认找最小类型,没有的话则提升
    • char如果没有找到char参数的方法,会直接提升至int
    • byte short 一步一步提升,比如,如果没有接收byte的参数方法 ,但是有接收short参数的方法,则会把byte提升到short。并调用接收short参数的方法

    2 传入的实际参数大于重载方法声明的形式参数,需要强制转换较小的类型,进行窄化转换,不然编译器就会报错

    3 this关键字

    只能在方法内部使用,表示对“调用方法的那个对象”的引用。

    如果在方法内部调用同一个类的另一个方法,不必使用this,直接调用即可。当前方法中的this引用会自动应用于同一类中的其他方法。

    public class A{

    void pick)()

    void pit(){ pick();}

    }

    可以写this.pick()但没有必要,会自动添加

    用法:

    1 返回对象引用 return this;

    2 将当前对象传递给其他方法: return Peller.peel(this); 调用另一个类的静态方法,并把该类的对象传递过去。

    3 构造器中调用构造器:为了避免重复代码。但是要注意的是,必须将构造器调用置于最开始处,且只能用this调用一个构造器,不能调用两个。

    4 带表数据成员:this.s

    4 static 的含义

    static方法中没有this。不能调用非静态方法。而非静态方法可以调用静态方法。

    5清理:终极处理和垃圾回收

    finalize() 方法,清理未使用对象(new)获得的内存资源。

    垃圾回收三点概念

    • 对象可能不被垃圾回收:存储空间没有用完,对象就总也得不到释放。
    • 垃圾回收并不等于“析构”
    • 垃圾回收只与内存有关:回收程序不再使用的内存。

    垃圾回收如何工作

    垃圾回收对于提高对象的创建速度,有明显的效果。存储空间的释放会影像存储空间的分配。java从堆分配空间的速度,可以和其他语言从堆栈上分配空间的速度相媲美。

    引用计数法:是一种简单但速度很慢的垃圾回收技术,常用来说明垃圾收集的工作方式,但似乎从未被应用于任何一种java虚拟机中。

    工作方式:每个对象含有一个引用计数器,当引用连接对象,引用计数加1,引用离开作用域或置为null,引用计数减1。引用计数为0时,就释放器占用的空间。

    缺陷:如果对象质检存在循环引用,可能会出现“对象应该被回收,但引用计数却为0”的情况。

    另一种方式思想是:对任何活的对象,一定能追溯到活在堆栈或静态存储区之中的引用。由此如果从堆栈和静态存储区开始,遍历所有的引用,就能找到所有活的对象。

    对于发现的每个引用,必须追踪它所引用的对象,然后是此对象包含的所有引用,如此反复下去,直到访问全部停止。

    基于上述思想是目前java虚拟机采用的思想,由此得到自适应垃圾回收技术

    1 停止-复制(stop-and-copy) :先暂停程序的运行,然后将所有存活的对象从当前堆复制到另一个堆,没有被赋值的全部都是垃圾。复制新的堆的时候,保持紧密排列

    这种方式效率低,原因:两个堆之间来回挪动,需要很多的空间,2 产生少量的垃圾时,这种方式会非常浪费

    2标记-清扫(mark-and-sweep):从堆栈和静态存储区出发,遍历所有引用,找出存活的对象。每当它找到一个活的对象,就给对象设置一个标记。当所有标记工作完成时,清理

    动作才会开始。没有标记的对象,将被释放,不会发生任何复制动作。所以剩下的堆空间是不连续的

    两个方法都必须在程序暂停的情况下进行。

    对于第一个方法(stop-and-copy),一些虚拟机解决方案是,内存分配以较大的“块”为单位。如果对象交大,它会占用单独的块。每个块都用相应的代数记录它是否存活。

    如果块在某处被引用,代数就会增加。垃圾回收器将对上次回收动作之后信分配的块进行整理。这对处理大量短命的对象很有帮助。垃圾回收器会定期进行完整的清理

    动作--大型对象仍然不会被赋值(只是代数会增加),内含小型对象的那些块则被赋值并整理。

    如果所有对象都很稳定,垃圾回收器效率低的化,就从停止-复制 切换到 标记-清扫 方式。标记清扫出现太多的垃圾碎片则再切换回停止-复制 方式。

    6 初始化

    初始化顺序

    1 静态变量>成员变量>构造器,

    2 按照声明顺序初始化

    静态变量在类首次加载时初始化,并且只初始化一次。 成员变量和构造器在new一个对象时初始化,可以初始化多次

    静态变量只占用一份存储区域,static关键字不能应用于局部变量。

    image.png

    显示的静态初始化-------静态代码块,只执行一次

    非静态实例初始化-------代码块,用来初始化每一个对象的非静态变量,这种语法对于支持“匿名内部类”的初始化是必须的,在构造器之前执行。

    数组初始化

    • Integer[] a = new Integer[数量] 初始化数组,并指定数组大小。为其分配内存空间,并初始化0 或null 或false。
    • Integer [] a = {} 在定义数组时就得指定元素,
    • Integer[] a = new Integer[]{} 这种方式不需要在定义数组引用时就初始化。比如

    a = new Integer[] {}; 可以分开。是最灵活的初始化方式

    可变参数列表

    void printArray(Object... args) 该参数接收下面三种参数,并转化成数组

    1 传多个参数 printArray(1, 2, 3, 4)

    2 传一个数组 printArray((Object[]) new Integer[]{1, 2, 3, 4})

    3 传空List printArray()

    重载时,会出现问题

    void f(Character... args)

    void f(Long... args)

    void f(Integer... args)

    此时我们不能使用空参调用方法,这样会没法编译

    void f(float, Character... args)

    void f(Character... args)

    上面方法不可以,会报错

    void f(float i, Character... args)

    void f(char c, Character...args)

    此方法为正确解法

    重点:所以,我们应该只在重载方法的一个版本上使用可变参数列表,或者压根就不使用它

    7 枚举类型

    public enum Spiciness{

    NOT, MILD, MEDIUM

    }

    Spiciness s = Spiciness.MEDIUM;

    for(Spiciness s : Spiciness.values()){ // 返回所有枚举值

    s.ordinal(); // s.ordinal() 枚举的整数值

    }

    可以与switch一起使用

    Spiciness degree

    switch(degree){

    case NOT: statement;

    default: statement;

    }

    相关文章

      网友评论

          本文标题:java编程思想5-初始化与清理

          本文链接:https://www.haomeiwen.com/subject/kjxgoctx.html