目录
一、字符串常量池
1.概念
![](https://i-blog.csdnimg.cn/blog_migrate/31ecda59edaa987932914ad5fc802ba4.png)
2.举例
public static void main(String[] args) {
String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");
String s4 = new String("hello");
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s3 == s4);
}
大家认为输出结果是什么呢?
分别是:true false false 下面边画图边解释:
对于第一句:String s1="hello";首先需要明确一个字符串对象由两部分组成:value和hash,value存放一个数组对象地址,数组存放的是字符串内容。
对于双引号引起的字符串,先去常量池查找是否有这个字符串,没有则放入常量池(String table 哈希表)中,并在堆和栈中放入对象:
对于第二句:String s1="hello";先去常量池查找是否有这个字符串,有这个字符串且没有new一个,则直接引用常量池的:
所以s1==s2是true;
对于第三句:String s3=new String("hello"); 先去常量池查找是否有这个字符串,有这个字符串不用添加,new Srting产生新的value和hash:
所以s2和s3比较地址时不一样,false。
第四个一是样的 会产生新的value和hash。
3.intern方法
①
public static void main(String[] args) {
char[] ch = new char[]{'a', 'b', 'c'};
String s1 = new String(ch);
String s2 = "abc";
System.out.println(s1 == s2);
}
以上结果为false,画图解释:
当加入intern方法:
public static void main(String[] args) {
char[] ch = new char[]{'a', 'b', 'c'};
String s1 = new String(ch);
s1.intern();
String s2 = "abc";
System.out.println(s1 == s2);
}
以上结果为:true,s1.intern()指s1指向的对象入池,如果常量池中存在则不入池,画图解释:
二、反射
1.概念
2.反射相关的类
3.Class类中相关方法
①常用获得类相关方法
②常用获得类中属性相关的方法,以下返回值为Field
③获得类中构造器相关的方法,以下方法返回值为Constructor相关
④获得类中方法相关的方法,以下方法返回值为Method相关
4.反射示例
①先定义一个类:
②获取类对象---三种方法
Class对象包含了有关类的信息,比如类的名称、字段、方法和构造函数等
第一种:使用 Class.forName("类的全路径名")
第二种:使用 .class 方法
第三种:使用类对象的 getClass() 方法
每一个Class对象只有一个,即:c1==c2,c1==c3;
③进行反射
<1>.newInstance() 创建类的实例
<2>.getDeclaredConstructor(Class...<?> parameterTypes)获取两个参数的构造方法(包括私有) 通过获得的构造方法调用newInstance(参数初始化)实例化
报错是因为毕竟访问的是私有方法,得确定真的要访问。
<3>.getField(String name) 获得成员变量(字段)
通过获得的字段修改实例对象的字段 调用set(修改结果)方法
<4>.getDeclaredMethod(String name, Class...<?> parameterTypes) 获得成员方法
通过对象调用获得的成员方法,初始化
三、枚举
1.定义一个枚举类型
该枚举类型里有3个对象:Red,Blue,Green.
2.枚举类型常用方法
3.枚举的方法来自于继承
上述中的方法来自于枚举类型所继承的Enum类,编译器默认继承。
会发现没有values()这个方法,那么枚举类型这个方法哪里来的?枚举类的values()方法是由编译器自动生成的静态方法。
4.枚举的构造方法
继承的Enum构造方法有两个参数,但是在定义枚举时没有写super,这是因为编译器已经默认处理过了。
枚举的构造方法默认是私有的,不可继承!!!
5.反射枚举类型
报错是因为枚举非常安全,不可以通过反射创建枚举对象。
四、Lambda表达式
1.概念
![](https://i-blog.csdnimg.cn/blog_migrate/103b37ab8666fcee49e353e98fb74118.png)
2.函数式接口
3.Lambda实现函数式接口例子
①无参数的
匿名内部类
Lambda表达式
②有参数的
匿名内部类
Lambda表达式
4.语法精简
5.变量捕获
![](https://i-blog.csdnimg.cn/blog_migrate/700ffcb7effe54402165bbe36a89346e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/60fe077053d610ba1b3c09a6ce865d24.png)
不能修改
6.Lambda在集合当中的使用
匿名内部类
Lambda表达式
这段代码可以遍历完列表是因为它使用了Lambda表达式来定义一个函数式接口的实现。Lambda表达式可以简洁地表示一个函数式接口的实现,这里的函数式接口是Consumer<String>
,它接受一个参数并返回void。list.forEach()
方法接受一个Consumer
接口的实现作为参数,它会将列表中的每个元素传递给该实现,并执行其中的代码。在这个例子中,Lambda表达式(String s) -> System.out.println(s)
定义了一个Consumer
接口的实现,它接受一个字符串参数并将其打印到控制台。因此,当list.forEach()
方法被调用时,它会遍历列表中的每个元素,并将每个元素传递给Lambda表达式中的代码进行处理,最终将列表中的所有元素都打印到控制台上。