Java基础(包装器,关键字,修饰符,Object)
文章目录
- 基本数据类型
- 类型转换
- 包装器类型
- 自动装箱,拆箱
- 128陷阱
- equals()和==
- 关键字
- 权限修饰符
- 抽象类和接口
- 区别
- 联系
- Object
- 定义
- 方法
- 重写euqals()方法时为什么要重写hashCode()方法
- 原因
基本数据类型
-
byte
-
boolean
-
char
-
short
-
int
-
long
-
double
-
float
类型转换
- 实线代表无信息丢失转换,虚线代表可能有精度损失的转换。例如,123456789是一个大整数,它所包含的位数比float类型所能够表达的位数多。当将这个整型数值转换为float类型时,将会得到同样大小的结果,但却失去了一定的精度。
int n = 123456789;
float f = n; // f is 1.23456792E8 - 当两个数的类型不一样时,先转换为一致的类型再进行计算。
- 有double转double
- 有float转float
- 有long转long
- 其余都转int
包装器类型
自动装箱,拆箱
int a = 100;
//自动装箱
Integer b = a;//Integer b = Integer.valueOf(a);
//自动拆箱
int c = b;//Integer c = Integer.intValue(b);
Integer d =100;
Integer e =1000;
Integer f = 1000;
sout(b==d);//true
sout(e==f);//false
sout(a == d);//true
128陷阱
Integer a = 128;
Integer b = 128;
System.out.println(a == b); //false
Integer c = 12;
Integer d = 12;
System.out.println(c == d); //true
这是因为Integer缓存机制,Integer会缓存-127 — 128范围的对象,当通过自动装箱创建Integer对象且数值位于这个范围内时,会直接从缓存里获取对象而非创建对象。而当超出这个范围时,就会创建对象,由此就会导致比较两个Integer时会出现不同的结果。
源码:
private static class IntegerCache {// 缓存的最小值,固定为 -128static final int low = -128;// 缓存的最大值,初始未赋值static final int high;// 用于存储缓存的 Integer 对象的数组static final Integer cache[];// 静态代码块,在类加载时执行static {// 缓存的最大值初始设为 127int h = 127;// 尝试从系统属性中获取自定义的缓存最大值String integerCacheHighPropValue =sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");// 如果获取到了自定义的缓存最大值if (integerCacheHighPropValue != null) {try {// 将自定义的缓存最大值转换为整数int i = parseInt(integerCacheHighPropValue);// 确保缓存最大值至少为 127i = Math.max(i, 127);// 确保缓存数组的大小不会超过 Integer.MAX_VALUEh = Math.min(i, Integer.MAX_VALUE - (-low) - 1);} catch (NumberFormatException nfe) {// 如果自定义的缓存最大值无法转换为整数,忽略该属性}}// 最终确定缓存的最大值high = h;// 创建缓存数组,数组大小根据最小值和最大值计算得出cache = new Integer[(high - low) + 1];int j = low;// 初始化缓存数组,将 -128 到 high 范围内的整数装箱为 Integer 对象并存储到数组中for (int k = 0; k < cache.length; k++)cache[k] = new Integer(j++);// 断言缓存的最大值至少为 127assert IntegerCache.high >= 127;}
equals()和==
-
==:
- 基本数据类型的值是否相当。
- 是否引用同一对象
-
equals():该方法来自于Object类,因此他的作用具体看如何实现的。(默认是比较引用是否相等)。
关键字
- static
- 修饰方法:static修饰的方法叫静态方法,静态方法属于类而不是类的实例,因此不需要创建实例即可用类名调用。
- 静态方法不能访问非静态方法和非静态成员变量,只能访问静态方法和成员变量。
- 修饰变量:可通过类名进行访问,属于类,在类加载时初始化。
- 修饰类:可以修饰内部类,叫做静态内部类。
- 静态内部类无法访问外部类的非静态方法和非静态成员变量(静态内部类在类加载时就已经存在了,而此时可能还没有创建对象),可以访问静态的成员变量和方法。
- 子类的实例无法调用父类的静态方法,但是可以通过子类的名字来调用父类的静态方法。
- 修饰方法:static修饰的方法叫静态方法,静态方法属于类而不是类的实例,因此不需要创建实例即可用类名调用。
- final
- 修饰方法:修饰方法时称为最终方法,无法被子类重写/覆盖。
- 修饰变量:修饰变量时成为常量。
- 如果是基本数据类型,一旦赋值就不可更改。
- 如果是引用数据类型,成员变量的值可以改变,但引用对象无法改变。
- 不可变类除外,即使没有final,不可变类的职业不可以改变(不可变类是不可以改变值的,如包装类,String,BigInteger , BigDecimal 和日期类)。
- 修饰类:修饰类时被称为最终类,无法被继承。
权限修饰符
权限修饰符 | 本类 | 同一包内的类 | 不同包的子类 | 不同包的非子类 |
---|---|---|---|---|
private | √ | × | × | × |
default | √ | √ | × | × |
protected | √ | √ | √ | × |
public | √ | √ | √ | √ |
抽象类和接口
区别
- 抽象类
- 单继承:一个类只允许继承一个抽象类。(需要重写所有的抽象方法)
- 可以有成员变量,无限制。
- 可以有抽象方法和普通方法。抽象方法无方法体。一个抽象类可以没有抽象方法。
- 支持构造方法。
- 接口
- 多实现:一个类可以实现多个接口(需要重写所有的抽象方法)
- 所有成员变量默认且只能是public static final,所有方法默认是public absrtact
- 只允许有抽象方法,不能有普通方法。
- 可以有default默认方法(可以有多个)。可以重写也可以不重写。
- 可以有static静态方法。(属于接口本身,实现类无法调用)。
- 如果一个类即实现了A接口,又实现了B接口,而A,B接口中有同名的默认方法,那实现类就必须重写默认方法。
- 不支持构造方法。
联系
- 都可以指代高度抽象的父体(实现多态,允许不同对象对同一消息做出不同反应)
- 都不能直接实例化
Object
定义
在Java编程语言中,Object类是所有类的根类。每个类都使用Object作为父类,所有对象(包括数组)都实现这个类的方法。
方法
- **toString():**返回该对象的字符串表示(默认打印的是"全类名 + @ + 哈希码值的十六进制")
- **equals():**默认比较类的引用是否相同。
- **hashCode():**返回该对象的哈希码值,该方法通过对对象的地址进行计算,不同对象的哈希码值一般不同。
- **getClass():**获取对象的字节码文件对象,需要用Class类来接收,sout打印出的是classs + 类的正名(正名 = 包名 + 类名)。
重写euqals()方法时为什么要重写hashCode()方法
原因
-
遵守hashCode的通用约定
如果两个对象通过equals()方法比较是相等的,那么他们的hashCode()方法必须返回相同的值。
-
保证哈希表的正常运行
- 当在哈希表中存储对象时,会先调用hashCode方法,根据哈希码值确定哈希表中的位置。如果没有重写hashCode方法,两个值相同的对象但哈希码值不一样,从而导致两个相同值的对象在Set中都存在。
class Person {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}// 重写 equals() 方法@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Person person = (Person) o;return age == person.age && name.equals(person.name);}// 重写 hashCode() 方法@Overridepublic int hashCode() {return Objects.hash(name,age);}
}public class Main {public static void main(String[] args) {Person person1 = new Person("Alice", 25);Person person2 = new Person("Alice", 25);Map<Person, String> personMap = new HashMap<>();personMap.put(person1, "Value");// 如果没有重写 hashCode() 方法,这里可能会返回 nullSystem.out.println(personMap.get(person2)); }
}