字符串常量池、反射、枚举、Lambda

目录

一、字符串常量池

1.概念

2.举例

3.intern方法

二、反射

1.概念

2.反射相关的类

3.Class类中相关方法

4.反射示例

三、枚举

1.定义一个枚举类型

2.枚举类型常用方法

 3.枚举的方法来自于继承

4.枚举的构造方法

5.反射枚举类型

四、Lambda表达式

1.概念

2.函数式接口

3.Lambda实现函数式接口例子

4.语法精简

5.变量捕获

6.Lambda在集合当中的使用

一、字符串常量池

1.概念
字符串常量池在 JVM 中是 StringTable类 ,实际 是一个 固定大小的HashTable ( 一种高效用来进行查找的数据结构,不同JDK版本下字符串常量池的位置以及默认大小是不同的)。Java 8 种基本数据类型和 String 类都提供了常量池。
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。

通过上面例子可以看出:使用常量串创建 String 类型对象的效率更高,而且更节省空间。
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.概念
Java 的反射 机制是在 运行 状态中,对于任意一个类,都能够知道这个类的 所有属性和方法 ;对于任意一个对象,都能够调用它的任意方法和属性,既然能拿到那么我们就可以修改部分类型信息;这种 动态获取信息 以及 动态调用对象方法 的功能称为java 语言的反射机制。可以利用 Java 的反射机制通过反射来获取所需的私有成员或是方法。
2.反射相关的类

3.Class类中相关方法

①常用获得类相关方法

常用获得类中属性相关的方法,以下返回值为Field

③获得类中构造器相关的方法,以下方法返回值为Constructor相关

获得类中方法相关的方法,以下方法返回值为Method相关

4.反射示例
Java 文件被编译后,生成了 .class 文件, JVM 此时就要去解读 .class 文件 , 被编译后的 Java 文件 .class 也被 JVM 解析为 一个对象,这个对象就是 java.lang.Class . 这样当程序在运行时,每个 java 文件就最终变成了 Class 类对象的一个实 例。我们通过Java 的反射机制应用到这个实例,就可以去 获得甚至去添加改变这个类的属性和动作 ,使得这个类成为一个动态的类。

①先定义一个类:

②获取类对象---三种方法

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.概念
lambda 表达式允许你通过表达式来代替功能接口。(匿名内部类的简化)

2.函数式接口

3.Lambda实现函数式接口例子

①无参数的

匿名内部类

Lambda表达式

②有参数的

匿名内部类

Lambda表达式

4.语法精简

5.变量捕获
匿名内部类中或Lambda表达式中定义的这个变量要么是被 final 修饰,如果不是被 final 修饰的,你要保证在使用 之前,没有修改。

不能修改

6.Lambda在集合当中的使用

匿名内部类

Lambda表达式

这段代码可以遍历完列表是因为它使用了Lambda表达式来定义一个函数式接口的实现。Lambda表达式可以简洁地表示一个函数式接口的实现,这里的函数式接口是Consumer<String>,它接受一个参数并返回void。list.forEach()方法接受一个Consumer接口的实现作为参数,它会将列表中的每个元素传递给该实现,并执行其中的代码。在这个例子中,Lambda表达式(String s) -> System.out.println(s)定义了一个Consumer接口的实现,它接受一个字符串参数并将其打印到控制台。因此,当list.forEach()方法被调用时,它会遍历列表中的每个元素,并将每个元素传递给Lambda表达式中的代码进行处理,最终将列表中的所有元素都打印到控制台上。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ambition…

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值