java(十四)Object解析

Object解析

所有类的最终父类都是Object

(1)native本地函数:就是指当前的方法内容有计算机具体的底层来实现 C/C++语言
         private static native void registerNatives();
    Object的这个类一旦被加载进方法区 则执行 注册本地方法registerNatives()
    就会在底层去创建一个Object对象并对类进行一定程度上初始化
    static {
        registerNatives();
    }

  (2) getClass() 所有Object的子类 可以继承到此方法 但是不能重写
    功能:主要就是获取当前类的信息(当前对象的类的对象 - Class类)
    万事万物接对象 类是不是对象呢? Class是 Java类的描述的一个类,就是字节码的类 .class文件当成一个对象去看待 Class就是该对象的类。是本地方法。
    public final native Class<?> getClass(); ***** 反射时说的多一些

(3)hashCode()
功能:获取当前对象的哈希值(在哈希表中的一个存储位置)
    本方法可以被重写:
        如果子类重写该方法 就意味着有子类去决定它自己的哈希值
        如果子类没有重写该方法 默认将该对象的地址当做哈希值
    public native int hashCode();    *****

   (4)equals()
功能:当前对象this和传入的对象obj是否相等
    对于Object而言 比较的其实就是两个对象的地址!!!如果子类没有重写该方法 那么也默认进行地址的比较!!!
    【一般而言 我们比较的应该对象的内容 而不是对象的地址】
    【== equals有什么区别:==比的永远是地址 equals在Object中与==一样 当然 也可以由子类自行重写】
    public boolean equals(Object obj) {    *****
        return (this == obj);
    }

(5)toString()
    功能:就是当我们直接打印一个对象时 打印的内容默认就是toString返回的内容
        返回当前对象的字符串形式
        Object obj=new Object();
        println(obj); == println(obj.toString());
        全类名+@+十六进制哈希值的字符串形式
    public String toString() {    *****
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }   

代码示例:


import java.io.Serializable;

//快捷方式 Alt+Shift+S
/*
 * Serializable
 * 数据从内存->外界(硬盘,网络) 数据要进行序列化  对象转二进制
 * 数据从外界->内存 数据要进行反序列化 二进制转对象 
 * 
 * Iterable(迭代 遍历  那就说明我们当前的类应该是一个容器(存储多个对象的类) )
 * 不适合对单一的实体类进行实现
 * 
 * Comparable 比较对象之间的大小(自然排序的前后关系) 区别于equals(比的是对象的内容是否相等)
 * 泛型
 * */
public class Person implements Serializable,Comparable<Person>{
	
	private int age;
	private String name;
	
	//构造函数-无参 有参
	public Person() {
		super();
	}

	public Person(int age, String name) {
		super();
		this.age = age;
		this.name = name;
	}
	
	/*
	//1.按照用户的想法去进行拼接就行
	@Override
	public String toString() {
		return "姓名:"+this.name+",年龄:"+this.age;
	}
	*/
	
	
	//2.通过快捷键的方式进行重写
	@Override
	public String toString() {
		return "Person [age=" + age + ", name=" + name + "]";
	}
	
	
	//修改器访问器(可选)
	public int getAge() {
		return age;
	}
	
	/*
	//1.自己重写equals函数 实现当前类中对象的比较内容
	@Override
	public boolean equals(Object obj) { //Object obj=new Point();
		//1.是否是自己比自己
		if(this==obj){
			return true;
		}
		//2.obj是否为空
		if(obj==null){
			return false;
		}
		//3.obj是否属于当前类Person类型
		if(obj instanceof Person){	//以两个对象的类型来判断
			Person other=(Person)obj;
			return this.age==other.age && this.name.equals(other.name);
		}
		return false;
	}
	*/

	//2.用快捷方式重写的equals
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		//getClass() 获取的是Person这个类的字节码的对象
		//obj.getClass() 获取的是obj这个对象所属类的字节码的对象
		
		//Person.java ->编译-> Person.class文件 只有一个 只有一个Person.class字节码文件对象
		//instanceOf的本质就是下面的这段
		if (getClass() != obj.getClass())	//以两个对象所属类的字节码对象来判断的
			return false;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	

	public void setAge(int age) {
		this.age = age;
	}


	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public int compareTo(Person o) {
		//看具体需求
//		return this.name.compareTo(o.name);
		return this.age-o.age;
		//负数 表示this比o 在前自然排序在前  小的意思
		//0    表示this比o 相等的意思 等效于equals
		//正数 表示this比o 在前自然排序在后  大的意思
	}
}
//
public class ObjectDemo01 {
	public static void main(String[] args) {
		Object obj = new Object();
		System.out.println(obj);
		//结果java.lang.Object@15db9742
		Person p1 = new Person(20, "老王");
		Person p2 = new Person(20, "老王");
		System.out.println(p1.toString());
		//结果Person [age=20, name=老王]
		System.out.println(p2);
		//结果Person [age=20, name=老王]
		
		//纯粹是比较两个对象的地址 0x123 == 0x456
		System.out.println(p1 == p2); //false
		
		//因为我们此时并没有重写Object的equals方法
		//所以我们在这里调用的equals 实质上比什么?
		//和  == 是一个意思 比的还是对象的地址 0x123 == 0x456
		System.out.println(p1.equals(p2)); //重写狗为true
		
		//需求:如果两个对象的属性完全相等 则表示两个对象相等的话
		//age相等 且 name相等
		System.out.println(p1.equals(p2));//true
		
		Person p3=new Person(20, "Angle");
		Person p4=new Person(18, "Bob");
		System.out.println(p3.compareTo(p4));//2
		System.out.println("===============================");
		
		System.out.println("abcd".compareTo("abcagghhh"));//3
		System.out.println("abcd".compareTo("abcdgghhh"));//-5
		System.out.println("10".compareTo("12"));//2
	}
}




StringBuffer类与StringBuilder类

我们对字符串本身不能进行修改 所以想要扩展字符串内容的话 只能重新创建一个字符串常量出来,出现一个问题 就是临时字符串的问题 就面代码中的的 "haha"。临时的字符串越多 也就意味着 字符串常量池中 没有被引用的字符串越多 垃圾越多!如何优化?如何解决?

代码示例:

package part03.StringBuffer与StringBuilder;

public class StringDemo {
	public static void main(String[] args) {
		/*
		此处的
		String s1="abc";
		String s2="abc";
		可以将s1和s2理解为基本数据类型的变量
		"abc"可以理解为基本数据类型的常量
		所以 s1 和 s2 这两个变量所存储的都是 "abc"在常量池中的地址
		常量池(字符串常量池 StringTable)
		*/
		String s1="abc";
		String s2="abc";
		System.out.println(s1==s2);			//true
		System.out.println(s1.equals(s2));	//true
		System.out.println("========");
		
		//s3 s4 存的是对象的地址
		String s3=new String("abc");
		System.out.println(s1==s3);			//false
		System.out.println(s1.equals(s3));	//true
		System.out.println("========");
		
		String s4=new String("abc");	
		System.out.println(s3==s4);			//false
		System.out.println(s3.equals(s4));	//true
		
		//我们对字符串本身不能进行修改 所以想要扩展字符串内容的话 只能重新创建一个字符串常量出来
		//出现一个问题 就是临时字符串的问题 就是下文的 "haha"
		//临时的字符串越多 也就意味着 字符串常量池中 没有被引用的字符串越多 垃圾越多!
		//如何优化?如何解决?
		String s5=s1+"haha";
		System.out.println(s1==s5);
	}
}

解决方法

StringBuffer类与StringBuilder类,也称之为是 字符串缓冲区(就是个动态扩容的数组而已!)如果说String是固定长度的且不能修改内容的字符串, SB就是长度可变的且能够修改内容的字符串。
不同点:
(1)StringBuffer和StringBuilder 方法都是一样的,唯一的区别就在于适用的场景不同,StringBuffer适用于多线程 StringBuilder适用于单线程。
 (2)StringBuilder是线程不安全的->没加锁(同步锁) 单        效率会更高;
          StringBuffer是线程安全的->加锁(同步锁)        多        效率会更低。
         虽然SB从名字上来看和String有关系 但是不是 SB是另起炉灶的字符串。

   (3) String和SB本质上都是字符数组; String中不支持字符数组扩容和修改内容的; SB中支持字符数组扩容和修改内容的。

字符串缓冲区SB是个动态扩容的数组,如果扩容的次数越多,那么也就意味着所用过的数组也越多 产生的垃圾越多!我们在使用String去操作的话,也会产生许多临时的字符串 产生的垃圾也多!此时怎么办呢?
     SB产生的垃圾主要集中在         堆内存
     String产生的垃圾主要集中在     方法区(字符串常量池)
     【JVM告诉你,GC在堆内存中活跃程度 比在方法区的活跃程度 要大的大的大的多!】
     【GC 垃圾收集器】
     【也就意味着 GC在堆内存中回收垃圾的效率要远远比在方法区高】
     (堆垃圾就像是家用垃圾桶,满了就清理)
     (方法区就像是垃圾场,满了才清理)
     【堆的垃圾被回收的很快 方法区的垃圾回收的很慢】
     综上而言 还是推荐使用SB

SB常用的功能

append(String str) 指将指定的字符串追加到次字符序列。

toString()返回此字符串表示形式,把value字符数组封装为字符串进行返回。

capacity()返回是当前的容量

length()指的是当前有效字符的个数

charAt(a)指的是获取 角标a处的字符

deleteCharAt(0)指的删除角标 0处的字符

indexOf(String str)查找当前字符的位置。

insert(offst,c)插入在offst插入c。

reverse() 反序。

代码示例:

import java.util.Arrays;

import part01.Object解析.Person;

public class StringBuildeDemo01 {
	public static void main(String[] args) {
		StringBuilder sb=new StringBuilder();
		StringBuffer sb2=new StringBuffer();
		String s=new String();
		
		sb.append(10);
		sb.append(new Person(30,"老李"));
		sb.append("hahalalaxixi");
		sb.append(true);
		System.out.println(sb.toString());
		//"10Person [age=30, name=老李]hahalalaxixitrue"
		System.out.println(sb.capacity());	//指的是当前value的容量
		System.out.println(sb.length());	//指的是当前value中有效字符的个数
//		System.out.println(sb.charAt(100));	//字符串角标越界:StringIndexOutOfBoundsException
		sb.deleteCharAt(0);
		System.out.println(sb.toString());
		sb.delete(0, 10);//[start,end)
		System.out.println(sb.toString());
		System.out.println(sb.indexOf("name"));
		sb.insert(5, "lala");
		System.out.println(sb.toString());
		System.out.println(sb.reverse());
		//toString()的新写法
		int[] arr={1,2,3,4,5,6,7,8,9,10};
		System.out.println(arrayToString(arr));
		System.out.println(Arrays.toString(arr));
	}

	private static String arrayToString(int[] arr) {
		if(arr==null){
			return "[]";
		}
		StringBuilder sb=new StringBuilder();
		sb.append('[');
		for (int i = 0; i < arr.length; i++) {
			sb.append(arr[i]);
			if(i==arr.length-1){
				return sb.append(']').toString();
			}
			sb.append(',');
		}
		return null;
	}
}

基本数据类型包装类

万事万物皆对象对象,所以我们的基本数据类型其实也有其针对的类描述。

    byte  - Byte;short  - Short;int  - Integer;long  - Long;float  - Float;double   - Double;char  - Character; boolean  - Boolean。

功能:

compareTo(Integer  anotherInteger) 在数字上比较两个Integer对象。

intValue() 以int型返回Integer的值。

toString() 将包装类型->字符串。

parseInt(String s) 将字符串参数作为有符号十进制整数解析。

reverse(int i) 反转指定int 型二进制补码中位数的值。

toBinaryString(int i) 转成2进制数。

toOctalString(int i) 转成8进制数。

toHexString(int i) 转成16进制数。

toString(int i) 默认转成十进制数

valueOf(int i)返回以个表示指定int值的Integer实例。等效于 new Integer()。

代码示例:

import java.net.Inet4Address;
public class NumberDemo01 {
	public static void main(String[] args) {
		Byte b=new Byte("10");
		Short s=new Short("10");
		
		Integer i1=new Integer(10);		//10
		Integer i2=new Integer(12);	//10
		Long l=new Long("10");
		Float f=new Float("10");
		Double d=new Double("10");
		Character c=new Character('a');
		Boolean bool=new Boolean("true");
		
		//成员函数
		System.out.println(i1.compareTo(i2));
		System.out.println(i1<i2); //【注意!】
		System.out.println(i1+i2);
		System.out.println(i1.equals(i2));
		System.out.println(i1==i2);
		System.out.println(i1.intValue()==i2.intValue());
		System.out.println(i1.toString());//将包装类型->字符串 等效于 10+""
		//静态函数
		System.out.println(Integer.parseInt("123")+1);	//默认以十进制解析字符串
		System.out.println(Integer.parseInt("10010101",2));	//以二进制解析字符串
		//java.lang.NumberFormatException
//		System.out.println(Integer.parseInt("10010102",2));	//以二进制解析字符串
		System.out.println(Integer.parseInt("102201012",3));//以三进制解析字符串
		//最高支持几进制?radix ∈  [2,36] 10个数字+26个字母
		System.out.println(Integer.parseInt("123123",36));
		System.out.println(Integer.reverse(123));//不是我们简单认为的123-321
		
		System.out.println(Integer.toBinaryString(149));
		System.out.println(Integer.toOctalString(149));
		System.out.println(Integer.toHexString(149));
		System.out.println(Integer.toString(149));	//不是Object重写来的
		//静态工厂模式
		System.out.println(Integer.valueOf(10));	//等效于 new Integer(10)
		
		/*
		 Character 当中最常用的就是判断字符的类型相关的函数
		 自行下去查API
		 */
	}
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值