一切皆对象(1)

——总结自《java编程思想》
在 java中一切都是对象,操作的标识符便是对象的一个“引用”。例:

String s;

这里所创建的只是引用,并不是对象 。如果此时向s发送一个消息就会返回一个运行时错误。因为此时s实际上并没有与任何的事务相关联。

对象存储位置

  1. 寄存器

    最快的存储区,位于处理器内部,数量有限,按需求分配,程序无法控制。

  2. 堆栈

    位于通用RAM(随机访问存储器)中,可通过堆栈指针进行空间分配,速度仅次于寄存器。创建程序时,java 系统必须知道存储在堆栈中的所有项的生命周期,以便上下移动指针。这一约束限制了程序的灵活性,所以虽然某些java数据存储在堆栈中——特别是对象引用,但是java对象并不存储在其中。

  3. 一种通用的内存储(位于RAM),用于存放所有的java对象。对于堆,编译器不需要知道存储的数据在堆里面存活时间多长,不过用堆进行存储分配和清理可能比用堆栈进行存储分配需要更多的时间。

  4. 常量存储

    常量值通常直接存放在程序代码内部。

  5. 非RAN存储

    数据完全存活于程序之外,不受程序的控制。两个最基本的例子就是流对象和持久化对象。

java 部分对象

基本类型:java 对于一些小的、简单的变量不用new来创建,而是创建一个并非是引用的“自动”变量,这个变量直接存储“值”并放置在堆栈中(而不是通过new放置在堆中),因此更加高效

java 提供了两个用于高精度计算的类:bigInteger、bigDecimal——以速度换取精度

java中的数组:java 确保数组会被初始化,而且不能在它的范围之外被访问。这种范围检查是以数组上少量的内存开销以及运行时的下标检查为代价的。当创建一数组对象时,实际上就是创建了一个引用数组,并且每个引用都会自动被初始化为一个特定的值。该值拥有自己的关键字null,一旦java看到null,就知道这个引用还没有指向某个对象。在使用任何引用前,必须为其制定一个对象;如果视图使用一个还是null的引用,在运行时就会报错。因此,常犯的数组错误在java中可以避免。

当用 new创建一个java对象时,它可以存活于作用域之外。

{
    String s = new String("string")
}

引用s在作用域终点就消失了,但是s指向的String对象仍继续占据内存空间。

static满足的需求:

  1. 只想为某特定域分配单一存储空间,而不去考虑究竟要创建多少对象。
  2. 希望某个方法不与包含它的类的任何对象关联在一起。

static就是没有this的方法。在static方法的内部不能调用非静态方法,反之则可以。使用static方法时,由于不存在this,所以不是通过向对象发送消息的方式来完成的。

equals 用来比较对象的内容而非对象的引用

如果对char、byte或者short类型的数值进行移位处理,那么在移位进行之前,它们会被转换成int类型,并且得到一个int类型的结果。只有数值右端的低5位才有用——防止移位超过int有具有的位数(因为2的5次方为32,int只有32位)。对一个long类型的数值进行处理得到一个long类型的结果,此时只会用到数值右端的低6位。

while(x = y){
 
}

如果y是一个非零值,在C和C++中 ,这种赋值结果为true,程序进入死循环。在java中,因为不会自动将int转换成bool,所以在编译时会抛出一个编译时错误。

对于类中的方法重载,区别方法靠的是参数列表而不是返回值。为什么不能用返回值区分重载方法?

当想要的是方法调用的其它效果(为了副作用而调用)而不是返回值,则无法区分重载方法。例:

void f(){}
int f(){return 1}

//调用方法
f() 无法区分是哪个f()方法

构造器初始化

在类的内部,变量定义的先后顺序决定了初始化的顺序。即使变量定义散布于方法定义之间,它们仍然会在任何方法(包括构造器)被调用之前得到初始化。

无论创建多少个对象,静态数据都只占用一份存储空间。static关键字不能作用域局部变量,因此只能作用于域。

class A {
    private static int numA;
    private int numA2;
    
    static {
        System.out.println("A的属性 : " + numA);
        System.out.println("A的代码块");
    }
    
    {
        System.out.println("A的成员变量  : " + numA2);
        System.out.println("A的非静态代码块");
    }
 
    public A() {
        System.out.println("A的构造器");
    }
}
 
class B extends A {
    private static int numB;
    private int numB2;
 
    static {
        System.out.println("B的静态字段 : " + numB);
        System.out.println("B的静态代码块");
    }
    
    {
        System.out.println("B的成员变量 : " + numB2);
        System.out.println("B的非静态代码块");
    }
 
    public B() {
        System.out.println("B的构造器");
    }
}
 
public class Test {
    public static void main(String[] args) {
        A a = new B();
        System.out.println("---");
        b = new B();
    }
}

结果为:在这里插入图片描述

由上图可知

父类的静态字段——>父类静态代码块——>子类静态字段——>子类静态代码块——>

父类成员变量(非静态字段)——>父类非静态代码块——>父类构造器——>子类成员变量——>子类非静态代码块——>子类构造器

父类A是执行了无参构造,也就是说,如果子类构造器中未显式指定父类构造器,那么将会默认执行父类的无参构造,此时,如果你重载了一个父类的有参构造而没有指定无参构造,那么编译将不会通过

发布了12 篇原创文章 · 获赞 1 · 访问量 203

猜你喜欢

转载自blog.csdn.net/qq_42885587/article/details/104341201
今日推荐