记录了一些遇到的问题

遇到了下面这样的问题,通过代码验证。

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class jjj {

	public static void main(String[] args) {
		
		List<String> l1 = new ArrayList<>();
		List<String> l2 = new LinkedList<>();
		l1.add("c");
		l2.add(new String( "c"));
		System.out.println(l1.equals(l2));
		
		List<String> l1_ = new ArrayList<>();
		List<String> l2_ = new ArrayList<>();
		l1_.add("a");
		l2_.add("a");
		System.out.println(l1_.equals(l2_));
		
		StringBuilder a = new StringBuilder("a");
		StringBuilder b = new StringBuilder("a");
		System.out.println(a.equals(b));
		//System.out.println(a==b);
		
		String a1 = new String("a");
		String a2 = new String("a");
		System.out.println(a1.equals(a2));
		
	}	
}

验证结果如下
在这里插入图片描述
假设上面库函数中的类全部都重写了equals函数,那么得到的结果应该是全部true。
但是并非如此,下面有关说明。

1>
List接口,无论是以何种方式实现,都是会根据其内部对象及顺序判断是否相等,对于这个可变类,实现了观察等价性。
下面代码验证:

		List<String> l1_ = new ArrayList<>();
		List<String> l2_ = new ArrayList<>();
		l1_.add("a");
		l1_.add("b");
		l2_.add("b");
		l2_.add("a");
		System.out.println(l1_.equals(l2_));

在这里插入图片描述

2>
关于StringBuilder类,往往关注其可变性,但忽略了其equals函数。
StringBuilder作为可变类,实现的是行为等价性。
还有关于String类。
首先,是存在常量池的,其用来存储字符串常量。

		String s_t1 = "a";
		String s_t2 = "a";
		System.out.println(s_t1.equals(s_t2));
		System.out.println(s_t1 == s_t2);

结果:
在这里插入图片描述
上面创建String对象没有使用 new String。
在创建字符串对象时,首先编译期,JVM会去常量池来检验该字符串是否应存在。
如果该字符串没有出现在常量区中,那么会在常量池中开辟一个空间来存贮字符串比如“a",接下来会在栈上开辟一个名为s_t1(遵循上面的举例)的空间,保存着常量池中的地址值。
如果该对象已经出现在常量池中,那么不会开辟新的空间,而是会在栈上开辟一个名为s_t1的空间来存储常量池中的地址。
String类的equals类是已经重写了的。 同时“==”也会判断出两个字符串相等,因为此时查看的是字符串存储的地址(在常量池中)。

接下来,如果是以new String来创建对象。在编译时期,会去常量池检验是否该字符串 比如“a"已经出现过,如果没有,会在常量池中创建这样的一个新的对象;在运行时期,构造器在堆中new一个空间,将“a"字符串复制过来,在栈中开辟名为ss1或者ss2的空间,存放new出来的对象的地址。
这样等价于当new一个对象时,可能创建了一个对象,也可能是创建了两个对象。

String类的库函数equals已经实现了重写。
StringBuilder类没有实现方法equals的重写,依旧等价于==,会去根据地址是否相等来判断。

		String ss1 = new String("a");
		String ss2 = new String("a");
		System.out.println(ss1.equals(ss2));
		System.out.println(ss1==ss2);
		

在这里插入图片描述

3>

import java.util.ArrayList;
import java.util.List;

public class test2 {
	
	public static void main(String[] args) {
	List<String> s = new ArrayList<>();
	s.add("s");
	
	for(String s_temp:s) {
		s.remove(s_temp);
	}
	
	}
}

在这里插入图片描述
即使去掉的元素是最后一个新添加的元素,依然会动态编译异常。
当remove操作过后,List中0对应为空,但此时还是会以String类型对List中的对象进行访问,此时产生了异常,类似于访问空指针的问题。

4>

		
		Integer i = 1;
		String s__ = true+"a"+i;
		System.out.println(s__);
		

输出结果为:在这里插入图片描述
可见,上述会发生动态类型转换,那么此时会进行一个其他类型向String类型的转换。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值