包装类
包装类 java.lang.*
1.包装----> 对基本数据进行进行包装
2.类----> 引用数据类型
基本数据 4类八种
包装类 8个包装类
8个包装类 与8个基本数据类型的意义是一模一样。----> jdk1.5(自动装箱/拆箱)
int VS Ineteger 代表任意一个整型的数据。
为什么还要提供8个包装类?
面向对象的编程语言。基本数据类型---->不能创建对象。
8个包装类,可以创建对象。类里面更加丰富(属性/方法)。丰富了基本数据类型的功能操作。
基本数据类型 | 默认值 | 包装类型 | 默认值 |
---|---|---|---|
byte | 0 | Byte | null |
short | 0 | Short | |
int | 0 | Integer | |
long | 0L | Long | |
char | \u0000 | Character | |
float | 0.0F | Float | |
double | 0.0 | Double | |
boolean | false | Boolean |
Integer
与int一致,代表任意一个整型的数据。
public final class Integer extends Number implements Comparable{}
Comparable:
compareTo(T t); 定义排序规则。 Integer底层已经自定义好了排序规则(默认升序)
两种都过时的构造器
Integer(int value);
Integer(String s);//将字符串的数据转换成Integer/int数据。
//都过时了。尽可能不要使用过时的方法。
static int compare(int x, int y) //以数字方式比较两个 int值。
int compareTo(Integer anotherInteger) ;// 0 -1 1
boolean equals(Object obj) //将此对象与指定的对象进行比较。
//Math.max()/min()
static int max(int a, int b) ;
static int min(int a, int b)
static int sum(int a, int b) //a+b
static String toHexString(int i) //将10进制数值转换成16进制的String
//toString()
static Integer valueOf(String s) //将字符串转 Integer/int数据。
static int parseInt(String s,int radix) //将字符串转 Integer/int数据。
创建对象
可以使用两种过时的构造器来创建对象,也可以使用和基本数据类型一样的方法创建包装类对象(自动装箱)
其底层运行的是Integer.valueOf( int i )
所有的包装类型的属性数据都不可变 private final int value
private static void demo2() {
//创建包装类对象的方式
//结论1: 所有的包装类型的数据都不可变 private final int value;
/* Integer num1 = new Integer(100);
Integer num2 = new Integer("-1234");
System.out.println(num1.toString());
System.out.println(num2);*/
//建议使用的方式: 与基本类型一致
int num = 100;
Integer num1 = 100;
Double d = 10.32763;
Character character = 97;
}
整数缓存池
private static void demo3() {
Integer num1 = 100;
Integer num2 = 100;
Integer num3 = new Integer(100);
Integer num4 = new Integer(100);
//100是基本数据类型 num1是对象
//基本类型的数据转换成包装类对象-----> 自动装箱 Integer.valueOf(100);
// 包装类名.valuesOf(基本类型 变量);
System.out.println("(num1==num2):" + (num1 == num2));//true
System.out.println("(num1==num3):" + (num1 == num3));//false
System.out.println("(num4==num3):" + (num4 == num3));//false
System.out.println("-----------------");
Integer n1 = 1000;
Integer n2 = 1000;
System.out.println(n1 == n2);//false
//IntegerCache.cache----> 整数缓存池----> 256个Integer的对象 -128-127
//为什么要在Integer提供整数缓存池设计思想?
// 提高资源利用率。避免出现内存的过度浪费。
//整数缓存池
//包装类/基本类型----> byte/short/int/long/char
//Byte----> ByteCache
//Short----> ShortCache
//Integer---->IntegerCache
// Long---> LongCache
// Character ---> CharacterCache
//都有整数缓存池。
}
数据比较
在引用类型之间使用 == 都是直接比较的地址
equals
compareTo 这个默认调用的compare 返回的是 0 -1 1
compare 用这三个都可以比较数值
private static void demo4() {
Integer n1 = 1000;
Integer n2 = 1000;
//比较保证类型的数据。
//equals
//compareTo
//compare
System.out.println(n1.equals(n2));//true
System.out.println(n1.compareTo(n2));
System.out.println(Integer.compare(n1.intValue(), n2.intValue()));
//包装类对象转成基本类型的数据-----> 自动拆箱-----> intValue()
//自动拆箱/装箱
//相互转换
//对象.xxxValue();
}
自动拆箱
Character
public static void main(String[] args) {
//包装的基本类型char的数据 字符 'a'
//0-127
//操作单字符
Character ch1 = 97;
Character ch2 = 'a';
Character ch3 = '\u5642';
char ch4 = ' ';
char ch5 = '\u0020';
//很多方法都是静态方法----->判断的方法
/*System.out.println(Character.isDigit(ch1));
System.out.println(Character.isLetter(ch2));
System.out.println(Character.isUpperCase(ch1));
System.out.println(Character.isLowerCase(ch1));
System.out.println(Character.isDefined(ch1));//unicode里面的字符规范
System.out.println(Character.isLetterOrDigit(ch1));
System.out.println(Character.isJavaIdentifierPart(ch1));//命名规则
System.out.println(Character.isWhitespace(ch5));
System.out.println(ch5);*/
//int Character.digit(char c,int radix); 将指定的字符数据转换成指定进制里面的数字
//System.out.println(Character.MIN_RADIX);
//System.out.println(Character.MAX_RADIX);
//2 8 10 16 36
//0-9 ASCII 48-57
/*char c = '9';
int n = c-48;
System.out.println(n)*/
;
char cc = 'A';// 10
//16/36 10
int digit = Character.digit('Z', 36);
System.out.println(digit);
System.out.println(Integer.parseInt("-1234", 10));
//String.length();//字符串里面字符个数 5
//char String.charAt(int index);//获得指定index的字符数据
System.out.println(Character.toUpperCase('a'));
System.out.println(Character.toLowerCase('B'));
}
Math
工具类,用的时候自己查
public static void main(String[] args) {
//Math类中常用方法
//算术运算+几何运算
System.out.println(Math.E);
System.out.println(Math.PI);
//常用方法
System.out.println(Math.random());//0.0-1.0
System.out.println(Math.pow(2, 3));
System.out.println(Math.abs(-10.736));
System.out.println(Math.max(10, 100));
System.out.println(Math.min(10, 100));
System.out.println(Math.round(10.567));//11
System.out.println(Math.sqrt(9));
System.out.println(Math.addExact(10, 20));
System.out.println(Math.subtractExact(20, 30));//-10
System.out.println(Math.multiplyFull(10, 20));
//System.out.println(Math.multiplyHigh(100000L, 2000000L));//0
System.out.println(Math.multiplyExact(10, 20));//200
}
Object
所有类的父类
方法
1. public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
//将对象转换字符串处理。显示此对象的16进制的hash。
//不同对象的hash值可以相同。hash冲突/碰撞。 不能看成内存地址值、
2. public boolean equals(Object obj) {
return (this == obj);
}
//比较2个对象是否相等。 底层: == 比较的内存地址值。
3. @HotSpotIntrinsicCandidate
public native int hashCode();
//获得对象的10进制的hash数据。
4. @HotSpotIntrinsicCandidate
public final native Class<?> getClass();
//获得任意一个引用/对象的Class类对象。
//获得正在运行期间的任意一个类或者接口的class文件。-----> 反射
5. @HotSpotIntrinsicCandidate
protected native Object clone() throws CloneNotSupportedException;
//使用对象克隆一个新的对象。
//要求: 对象的类型必须支持被克隆。 类 必须要实现标记接口: java.lang.Cloneable
//线程之间的通信
//都不能随便调用 必须在 synchronized方法/代码块使用
public final native void notify(); //唤醒随机一个wait的线程
public final native void notifyAll();//唤醒随机所有wait的线程
public final void wait() throws InterruptedException;//当前线程等待--->notify
public final native void wait(long timeoutMillis) throws InterruptedException;
//时间内等待----> 超时/时间内唤醒
toString
将对象转String。打印引用数据类型的引用/对象 默认调用toString
常用: 实体类上重写toString
@Setter
@Getter
@ToString
public class Student /*extends Object*/{
private Integer id;
private String name;
private Integer age;
private Double score;
}
public static void main(String[] args) {
Student student = new Student();
student.setId(1);
student.setName("张三");
student.setScore(100d);
student.setAge(20);
//查询Student对象的数据
//1.遍历式调用student里面的get
//2.打印输出对象----> 使用类管理代码 使用对象封装数据。
System.out.println(student.toString());//com.javasm.lang.Student@880ec60
}
equals+hashcode
//使用java提供方式:
//实现: 比较2个对象是否一致/相等。
private static void demo2() {
Student student1 = new Student(1,"张三",20,100D);
Student student2 = new Student(1,"张三",20,100D);
//比较对象
//1. 比较运算符 == 比较内存地址值
//System.out.println(student1 == student2);//false
System.out.println(student1);
System.out.println(student2);
//Student(id=1, name=张三, age=20, score=100.0)
//Student(id=1, name=张三, age=20, score=100.0)
//一个对象。 2个对象应该是相等的。 true====> 对象维护数据(对象属性)。
//2.比较数据 equals
//System.out.println(student2.equals(student1));// == false
//3.hashcode-----> 验证2个对象是否不等。
//在hash算法,对象的hash不同的,对象就是不等。
//hash存在弊端。hash会经常碰撞。2个对象的hash值一样,不能直接认为2个对象是相同的。
//不同的对象的hash值有可能是一致的。
//对象相等的规则: 自定义的。学生的id,name,age,score都一样的话,对象是相等。
System.out.println(student2.equals(student1));
//jvm有规则: 2个对象equals为true,这2个对象的hash值必须相同。
//重写了equals,必须重写hashCode。 2个不分家。
System.out.println(student1.hashCode());
System.out.println(student2.hashCode());
/*String str1 = new String("Ma");
String str2 = new String("NB");
System.out.println(Integer.toHexString(str1.hashCode()));
System.out.println(Integer.toHexString(str2.hashCode()));*/
}
@Setter
@Getter
@ToString
@AllArgsConstructor
@NoArgsConstructor
//@EqualsAndHashCode //类的所有的属性都参与
public class Student /*extends Object*/ {
private Integer id;
private String name;
private Integer age;
private Double score;
//在类中 重写equals----> 比较数据的
//对象相等的规则: 自定义的。学生的id,name,age,score都一样的话,对象是相等。
//比较2个对象的属性的数据是否都相等的。
//alt+insert+选择
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (!(obj instanceof Student)) return false;
Student student = (Student) obj;
return Objects.equals(this.id, student.id) &&
Objects.equals(this.name, student.name) &&
Objects.equals(this.age, student.age) &&
Objects.equals(this.score, student.score);
}
@Override
public int hashCode() {
return Objects.hash(id, name, age, score);
}
}
为什么比较2个对象一定要重写equals+hashcode?
1.比较
1.1. == 内存地址值
1.2 equals 默认底层 ==
1.3 hashcode 比较2个对象是否不等。不同对象的hash数据可能是一致的。
2. 重写 equals-----> 比较规则 进行编码 true
3. 2个对象调用 equals为true 2个对象的hash值肯定是相同的
4. 必须要重写hashcode
clone
克隆。
对象的克隆。创建对象的一种方式。
1.new 构造; 2. clone 3. 序列化 4. 反射
根据对象/引用创建另外一个新的对象。
1.源对象与克隆的对象是同一个吗?
2.克隆的对象的属性的数据是否原对象的数据一致呢?
3.克隆的对象是否会执行类的构造方法?
4.修改其中一个对象的属性的数据,另外一个对象的数据是否会改变?
一个类能被clone的话,必须实现Cloneable接口
注意clone方法在Object类里面是protected,建议在子类里面重写扩大访问范围
区分浅克隆和深克隆,深克隆:克隆完对象后再对对象引用类型的属性进行克隆
@Setter
@Getter
@ToString
public class Email extends Object implements Cloneable{
private Integer id;
private String sender;//发送者
private String receiver; //收件人
private String content; //发送内容
private String[] attachment;//附件:文件 图片
@Override
public Email clone() {
try {
Email clone = (Email) super.clone();
//clone.setAttachment(Arrays.copyOf(attachment,attachment.length));
clone.setAttachment(attachment.clone());
//遍历式对属性依次赋值
return clone; //浅克隆
} catch (CloneNotSupportedException e) {
System.out.println("类型没有支持被克隆,类没有实现标记接口Cloneable");
throw new RuntimeException(e);
}
}
public Email(int id, String sender, String receiver, String content, String[] attachment) {
System.out.println("Email。。。。。。有参构造");
this.id = id;
this.sender = sender;
this.receiver = receiver;
this.content = content;
this.attachment = attachment;
}
public Email() {
System.out.println("无参构造...........");
}
}
private static void demo3() {
Email sourceEmail = new Email();//无参构造
sourceEmail.setId(1);
sourceEmail.setSender("123@qq.com");
sourceEmail.setReceiver("222@qq.com");
sourceEmail.setContent("恭喜你,中奖了!!!");
String[] array = {"美女1.jpg", "美女2.jpg", "美女3.jpg"};
sourceEmail.setAttachment(array);
//将sourceEmail转发给他们
//克隆一个Email的实例
Email cloneEmail = sourceEmail.clone();
System.out.println("(sourceEmail==cloneEmail):"+(sourceEmail==cloneEmail));
System.out.println("sourceEmail:"+sourceEmail);
System.out.println("cloneEmail:"+cloneEmail);
//发送给他人 好友A
cloneEmail.setSender(cloneEmail.getReceiver());
cloneEmail.setReceiver("好友@qq.com");
cloneEmail.getAttachment()[0] = "帅哥1.jpg";
System.out.println("-----------------------修改一个对象的数据---------------");
System.out.println("sourceEmail:"+sourceEmail);
System.out.println("cloneEmail:"+cloneEmail);
//新的需求: 不要影响另外一个对象的数据。----> 不使用共同的一块内存即可。
//深克隆 解决 浅克隆里面的问题。(在重写的clone的方法中,需要对属性执行遍历式的克隆)
//
//1.源对象与克隆的对象是同一个吗? 不是 新创建一个新的对象
//2.克隆的对象的属性的数据是否原对象的数据一致呢? 一模一样
//3.克隆的对象是否会执行类的构造方法? 没有。与类的构造无关。 jvm底层的机制
//4.修改其中一个对象的属性的数据,另外一个对象的数据是否会改变? 有可能。引用数据类型(包装类+String)。
}
克隆的内存形式
Class
代表程序里面,任何一个对象/引用的类类型
将Class类看出每个类或者接口的class文件。一份class文件对应者一个Class类对象
//获得Class类对象的方式:
//1. Class getClass(); //引用数据类型
//使用很少----> 与对象的耦合度很高
Student student = new Student();
Class aClass = student.getClass();
//aClass ===>Student.class 所有的内容都可以根据aClass获得
System.out.println(aClass.getSimpleName());//类名/接口名/枚举类...
System.out.println(aClass.getName());//com.javasm.lang.Student 类全限定名称(路径)
//2.任意数据类型都可以操作
// 类型名称.class;
private static void demo5() {
//类名.class; 推荐
Class aClass = int.class;
System.out.println(aClass.getName());
System.out.println(aClass.getSimpleName());
Class studentClass = Student.class;
Class cloneableClass = Cloneable.class;
Class weekClass = DayOfWeek.class;
}
//3.Class Class.forName(String path);
//配置文件中----> 路径 ----> 第二阶段 xml yml
private static void demo6() {
//Class.forName("类/接口/枚举类完整路径");
//加载第三方类库资源的时候-----> 帮助检测是否引入第三方jar
//扩展程序
try {
Class aClass = Class.forName("com.javasm.lang.Student");
} catch (ClassNotFoundException e) {
System.out.println("找不到Student.class");
}
}