基础

匿名对象

匿名对象的作用在于一次性使用对象内部方法时,由于再无引用引用之,Java的自动回收机制会视作垃圾处理,性能优化方案

java的几种基本数据类型

ps:在选择不同类型的数字的数据类型时,主要目的是节省空间

类型名 字节 特性
byte 8位1字节 有符号的,-128~127,byte 类型用在大型数组中节约空间,主要代替整数,因为 byte 变量占用的空间只有 int 类型的四分之一
short 16位2字节 有符号,-32768~32767,。一个short变量是int型变量所占空间的二分之一
int 32位四字节 -2,147,483,648~2,147,483,647
long 64位8字节 -9,223,372,036,854,775,808~9,223,372,036,854,775,807,种类型主要使用在需要比较大整数的系统上

浮点数

类型名 字节 特性
float 32位四字节 符号位1,指数位8,尾数位23

equals和hashCode

为什么重写equals之后,hashCode也要重写

// 重写equals的原则
1、自反性:对任意引用值X,x.equals(x)的返回值一定为true. 
2、对称性:对于任何引用值x,y,当且仅当y.equals(x)返回值为true时,x.equals(y)的返回值一定为true; 
3、传递性:如果x.equals(y)=true, y.equals(z)=true,则x.equals(z)=true 
4、一致性:如果参与比较的对象没任何改变,则对象比较的结果也不应该有任何改变 
5、非空性:任何非空的引用值X,x.equals(null)的返回值一定为false


// hashcode
hashCode是jdk根据对象的地址或者字符串或者数字算出来的int类型的数值,也就是哈希码,哈希码并不是完全唯一的,它是一种算法,让同一个类的对象按照自己不同的特征尽量的有不同的哈希码,但不表示不同的对象哈希码完全不同。可能会出现hash碰撞。
在Java中,哈希码代表对象的特征。  

// 原生的hashcode
object的hashCode返回对象的内存地址经过处理后的结构,每个对象的内存地址不一样,所以hash码也不一样

// 重写hashcode的基类
String类的hashcode是根据string字符串内容来返回的,所以字符串相同的hashcode也相同\

// Integer类的hashcode返回就是该对象包含的那个整数值

// 为什么重写equals要重写hashcode?
因为如String重写equals,如果不重写hashcode的话,两个字符串虽然相等,但是它们的hashcode却不想等,这样容易产生歧义

// 重写规则
①两个obj,如果equals()相等,hashCode()一定相等 
②两个obj,如果hashCode()相等,equals()不一定相等(hash碰撞)
序列化
// 作用
简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来。虽然你可以用你自己的各种各样的方法来保存object states,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。
// 思考,如何自行实现序列化
java对象的状态在于他的属性而不是方法,如果将属性遍历整合成为字符串,然后按照约定的转换规则重新new出对象,这样也能实现序列化,但是缺陷是,如果在作为字符串的期间,类发生了变更,那么转换的规则将不再适用,所以需要版本号。
// 序列化机制
某个类实现Serializable接口,而没有其它任何处理的话,在序列化对象时,不仅会序列化当前对象本身,还会对该对象引用的其它对象也进行序列化
// 阻止默认序列化 transient关键字
当某个字段被声明为transient后,默认序列化机制就会忽略该字段。如类的某个默认值属性
// 自定义序列化writeObject和readObject
public class Person implements Serializable {
    transient private Integer age = null;
    // 自定义序列化
    private void writeObject(ObjectOutputStream out) throws IOException {
        // 先执行默认序列化
        out.defaultWriteObject();
        // 显示写入age
        out.writeInt(age);
    }
    // 自定义反序列化
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        // 执行默认反序列化
        in.defaultReadObject();
        age = in.readInt();
    }
}

第二类序列化方Externalizable

向下转型,向上转型

Dog dog = new Dog();
Dog类型的引用指向一个Dog类型的实例
引用类型的转换:
1.在Java当中不是任意引用数据类型之间都能进行转换
2.Java中父类的引用指向子类对象是自动成功的
// 向上转型
Dog extends Pet
Pet pet = new Dog
父类的引用指向子类的实例


// 向下转型(强制类型转换)
Pet pet = new Dog();
Dog dog = (Dog) pet;
注:如果向下转型想要编译和运行都成功,必须使用强制转型语法,还必须要求运行起来父类引用确实指向该子类的对象


// 结论
1.在引用数据类型中,只有有继承关系的类型才能进行类型转换;
2.类型转换只是转换看待对象的引用的类型,对象本身没有也不可能参与转换(如何理解:意思就是在地址上标明的类型变换了,而堆中实体的类型并没有变化,所以当子类向上转型为父类的时候还是会调用子类的方法)
3.记住变化的只是引用类型,而不是实际类型,如果父类引用想要变成子类的引用向下转型,那么必须保证这个父类引用原来指向的就是该子类的一个实例
ex:
Pet pet = new Dog();
getPet(pet)
private void getPet(Pet pet){
    // 至始至终这个pet都是一个Dog实例并没有产生任何变化,不管在任何一个阶段调用它都会执行Dog类的方法,类型转换永远只是转换表面的东西也就是引用,而不是实体
    if(pet instance of Dog){
           Dog dog = (Dog)pet;
    }
}

重要概念,堆区还是栈区

Heap space 堆空间:所有存活的对象在此分配
Stack space 栈空间:方法调用时保存变量对象的引用或变量实例,也就是局部变量的基本数据类型的值才会存在栈区,任何成员变量无论他是基本数据类型还是引用类型都会存在于堆区
Perm space:保存已经加载的类的信息
注意:所有活着的对象和对象的成员变量无论是基本数据类型还是引用数据类型,都会存在于堆区

基本数据类型的转型

// int 比byte,short,char范围大,比long范围小
// double比float精确 当double转为float将丢失精度
byte,short,char → int → long → float → double
byte,short,char不会相互转换,计算时会先转成int,boolean类型不可以转换成其他数据类型
向上转型eg:
int i=123;
long l = i; // 自动向上转型
float f =3.14F;
double d = f; 自动向上转型

向下转型eg:
在java中默认整数类型是int,默认的浮点类型是double , double比float精确
long l = 123L; // 自动转为long
int i = (int) l; // 必须强转
double d = 3.14  // 自动转为double
float f = (float) d;// 必须强转

java为什么long后面要加L?float后面要加F?

java的内存体制
example:
long fw = 10000000000L;
实际上内存中fw只是一个long类型的变量,它存在于向stack(栈)中,数值并不在其中存放,它指向heap(堆)中另一块真正存放数值的内存,加L的目的就是为了让heap中也创建一块long类型所需要的内存,用来来放数值。
所以说=前后两者其实是在不同的两块内存,只不过有个无形的指针将两者连接起来了
注:












你可能感兴趣的:(基础)