1.面向对象的三大特点
封装、继承、多态
1.1封装
private (关键字) 是一个权限修饰符
可以修饰成员(成员变量和成员方法)
-
作用:保护成员不被别的类使用
针对private所修饰的成员变量,如果需要被其他的类使用,提供相应的额外的操作方法:
提供get变量名()用户获取成员变量(被private)的值,方法的修饰符时public
提供set变量名(参数)方法,用户设置成员变量的值 方法也必须使用public进行修饰
/*
类 所包含的应该是与其相关的成员
*/
public class Student {
//成员变量
String name;
private int age =18;// 在声明成员变量的时候 可以给其赋予一个默认值
public int getAge(){
return age;
}
public void setAge(int a){
if(a < 0 || a > 120){
System.out.println("您输入的年龄不合法");
}else{
age = a;
}
}
}
测试类
/*
类 所包含的应该是与其相关的成员
*/
public class Student {
//成员变量
String name;
private int age =18;// 在声明成员变量的时候 可以给其赋予一个默认值
public int getAge(){
return age;
}
public void setAge(int a){
if(a < 0 || a > 120){
System.out.println("您输入的年龄不合法");
}else{
age = a;
}
}
}
1.2this关键字
public void setName(String name ){
System.out.println(name);
this.name = name;//将局部变量的name赋值给成员变量的name 可以使用this
}
this修饰成员变量;
可以区分成员变量和局部变量:如果方法的形参和成员变量同名,不带this修饰的变量指的是形参,而this修饰的是成员变量
什么时候使用this?解决局部变量隐藏(屏蔽)成员变量
this的内存原理:
this代表当前调用方法的对象。哪个对象调用当前的方法,this就代表那个对象
this代表本类的当前对象

标准的java类的写法
标准的java类 也称为java bean
/*
类 所包含的应该是与其相关的成员
*/
public class Student {
//成员变量
private String name;
private int age =18;// 在声明成员变量的时候 可以给其赋予一个默认值
public String getName(){
return name;
}
public void setName(String name ){
this.name = name;//将局部变量的name赋值给成员变量的name 可以使用this
}
public int getAge(){
return age;
}
public void setAge(int age){
if(age < 0 || age > 120){
System.out.println("您输入的年龄不合法");
}else{
this.age = age;
}
}
}
1.3 封装思想
封装是面向对象的三大特征之一。
是面向对象编程语言对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界是无法直接操作的。
封装原则:
将类的某些信息隐藏在类的内部,不允许外部程序直接访问。而是通过该类提供的方法来实现对隐藏信息的操作和访问。
成员变量使用private修饰 提供对象的getXxx()和setXxx()方法
封装的好处:
通过方法来控制成员变量的操作,提高代码的安全性
把代码用方法进行封装,可以提高代码的复用性。
1.4 java中封装的体现
1 对于成员变量的封装 使用private
2 类体现的也是对一类事物的属性和行为的封装
3 方法体现了封装的思想:就是将某一个功能封装在其中。
2.构造方法
构造方法也成为构造器(constructor),用于对象的初始化。构造方法是一个创建对象时被自动调用的特殊方法。目的就是对对象进行初始化。
构造方法的名称要与类名完全一致。构造方法没有返回值(void也不写)
Java通过new关键字来调用构造方法,从而返回该类的一个实例对象,是一种特殊的方法
public Student(){
// System.out.println("student的无参构造被调用...");
}
2.1构造方法的注意事项
public static void main(String[] args) {
String s1 = "aaaa";//直接赋值
String s2 = new String();//创建一个空字符串
char[] c = {'a','b','c'};
String s3 = new String(c);//字符数组
byte[] b = {97,98,99};
String s4 = new String(b);//字节数组
System.out.println("s1=" + s1);
System.out.println("s2=" + s2);
System.out.println("s3=" + s3);
System.out.println("s4=" + s4);
}
4.3 创建字符串对象的两种方式的区别
4.3.1.通过构造方法创建
使用new创建字符串对象,每一次new都会申请一个内存空间,虽然内容都是相同的,但是所对应的内存地址是不同的。
char[] c = {'a','b','c'};
String s3 = new String(c);//字符数组
String ss3 = new String(c);
上面的代码。jvm会首先创建一个字符数组,然后每一次new 的时候 都会有一个新的地址,只不过s3 和ss3参考的字符串的内容是相同的
4.3.2 直接赋值的方式创建
使用“”方式给出的字符串,只要字符序列相同(顺序和大小写)。无论在程序代码中出现几次,jvm都只会建立一个String对象,并在字符串常量池(String pool)中维护
java中的三种常量池:
字符串常量池 class文件常量池 运行时常量池
1 字符串常量池(又称为全局字符串池)。
jvm所使用的内存中,字符串作为一种特殊的数据类型,占据了大量的内存,且字符串有着大量的重复,由于字符串本身具有不可变性,因此使用字符串常量池对于同样的字符串可以起到一个缓存的作用,防止多次内存分配,从而提供内存的利用率
2 运行时常量池
当程序运行到某个类的时候,class文件中的信息就会被解析到内存的方法区的运行时常量池中,每个类都有一个运行时常量池。
3 class文件常量池
class常量池是在编译后每个class文件都有的,class文件中除了包含类的版本 字段 方法 接口等描述信息,还有一项信息就是常量池,用于存放编译器生成的各种字面量和符号的引用。
5 JVM内存模型
jvm从大的方面分为:堆区 栈区 方法区
栈区: 细分为java虚拟机栈 和本地方法栈
堆内存可以划分为 新生代 老年代
新生代: Eden区 from区 to区
划分出来的各个区域 分别保存不同的数据 并且在一般情况下 期采取的内存回收策略也是不同。
5.1. 堆内存
堆内存是jvm内存模型中最大的一块区域,被所有线程共享。是在jvm启动的时候进行创建。几乎所有的对象的空间分配都是在堆区来进行分配。
考虑到jvm的内存回收机制,堆内存划分为新生代和老年代两个区域(默认的新生代和老年代的空间大小比例为1:2).新生代可以在划分为Eden区,From 区(s0) to区(s1),三者的比例(8:1:1) 几乎所有的新对象的创建都是在eden区 完成。在垃圾回收(GC)过程中,Eden区的活跃的对象会被迁移到Survior区,当在达到一定的年龄(经过一定的垃圾回收算法测处理),会被转移到老年代中。
堆内存在物理上可以使不连续,但是在逻辑上需要满足连续。在实现时。可以实现成固定大小的,也可以是可扩展的。
5.2.方法区
方法区又被称为永久代,我们所讲的模型是(Hotsport最常见的jvm的模型)。同样 也是被所有的线程所共享的,该区域主要保存类的信息,静态变量,常量和编译器编译后的代码等数据
jdk7中,将永久代中的字符串常量池移动到堆中。jdk8 撤销了永久代 ,引入了元空间
方法区不需要连续的内存,可以选择固定大小或者可扩展,并且还可以选择不实现垃圾回收,相对而言,垃圾收集行为在这个区域是比较少见的,但并非数据进入方法区就如永久代的名字一样永久存在了。这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载,圾回收机制的条件是相当苛刻的。
这段程序,以指数级不断的生成新的字符串,这样可以比较快速的消耗内存。
可以通过异常信息看到出现堆内存的异常,在jdk1.8之后,字符串常量池由永久代(方法区)转移到堆中
jvm的内存参数的设置
6.字符串的比较
#
public static void main(String[] args) {
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2);//true
// 使用字符数组构造一个字符串
char[] c = {'a','b','c'};
String s3 = new String(c);
String s4 = new String(c);
System.out.println(s3 == s4);//false
String s5 = new String("abc");
String s6 = new String ("abc");
System.out.println(s5==s6);// false
System.out.println(s1 == s3);//false
System.out.println(s4 == s5);//false
}
以上对于字符串的比较使用的是== 经过分析可以知道:==比较的是两个字符串对象的引用的地址是否相同。
比较字符串的内容相同:
如果要比较两个字符串的内容是否相同 则使用equals方法
System.out.println(s1.equals(s3));
System.out.println(s4.equals(s6));
System.out.println(s1.equals(s7));//false
System.out.println(s1.equals(s8));//false
System.out.println(s1.equalsIgnoreCase(s7));//true
System.out.println(s1.equalsIgnoreCase(s8));//true
需求:模拟完成用户登录
已知用户名和密码,请用程序来实现用户登录,总共有三次机会,登录之后要给出相应的提示。
import java.util.Scanner;
public class LoginTest {
public static void main(String[] args) {
// 假设用户名和密码是已知的 分别为
// String username = "lanqiao";
// String password = "123456";
//用户登录时 用户名和密码有用户从键盘输入 用户最多可尝试三次
for(int i = 0 ; i < 3 ;i++){
// 从键盘录入用户名和密码
Scanner sc = new Scanner(System.in);
System.out.println("请输入您的用户名:");
String inName= sc.nextLine();
inName=null;
System.out.println("请输入您的密码:");
String inPassword = sc.nextLine();
inPassword=null;
//比较用户输入的用户名和密码是否与已知的用户名密码一致
// 当进行字符串和一个变量比较的时候 ,一定要将字符串常量放在equals的前边 这样可以有效的避免空指针异常的出现
if("lanqiao".equals(inName)&&"123456".equals(inPassword)){
System.out.println("登录成功");
break;
}else{
if(2 - i == 0){
System.out.println("您的账户已经被锁定,请联系管理员");
}else{
System.out.println("用户名或密码有误,登录失败,您还有"+(2-i)+"次机会!");
}
}
}
}
}
遍历字符串
从键盘录入一个字符串,使用程序实现在控制台遍历该字符串。
public static void main(String[] args) {
//从键盘输入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入您要遍历的字符串:");
String str = sc.nextLine();
// 获取数组的长度 使用数组的length属性 获取字符串的长度 使用的是String类的length方法
for(int i = 0 ; i < str.length();i++){
char c = str.charAt(i);
System.out.println(c);
}
}
统计字符的次数
键盘录入一个字符串,统计该字符串中大写字母 小写字母 数字出现的次数 (不考虑其他字符)
对于一个字符判断他是大写字母 小写字母 数字 直接判断:
大写字母: ch >= 'A' && ch<='Z'
小写字母:ch>='a'&& ch<='z'
数字:ch>='0'&&ch<='9'
public class CountCharNum {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入您要统计的字符串:");
String str = sc.nextLine();
// 定义字符统计的变量
int bigCount = 0;
int smallCount = 0 ;
int numberCount=0;
for(int i =0 ; i < str.length();i++){
char ch = str.charAt(i);
if(ch >='A'&& ch<='Z'){
bigCount++;
}else if(ch >='a'&& ch<='z'){
smallCount++;
}else if(ch >='0'&& ch<='9'){
numberCount++;
}
}
System.out.println("大写字母的个数为:" + bigCount);
System.out.println("小写字母的个数为:" + smallCount);
System.out.println("数字的个数为:" + numberCount);
}
}
字符串反转:
定义一个字符串,实现字符串的反转 从控制台输入abc 输出结果为cba
7 String类的常用方法
public static void main(String[] args) {
String str = "abdcdadcd";
System.out.println(str.indexOf("a"));//0
System.out.println(str.lastIndexOf("a"));//5
}
String s = String.valueOf(123);//将整数123 转换为字符串123
8 String的常见陷阱
String str1 = "abc";
String str2 = new String("abc");
字符串常量存储在字符串常量池中,并且是共享
字符串非常量对象 存储在堆中
public static void main(String[] args) {
String s1 = "hello";
String s2 = "world";
String s3 = "hello" +"world";
String s4 = s1 +"world";
String s5 = s1 + s2;
String s6 = (s1 + s2).intern();
String s7 = "helloworld";
System.out.println(s3==s4);// false
System.out.println(s3 == s7);//true
System.out.println(s3==s5);//false
System.out.println(s4==s5);//false
System.out.println(s3==s6);//true
}
public static void main(String[] args) {
String str1 = new StringBuilder("计算机").append("软件开发").toString();
System.out.println(str1.intern()== str1);//true
String str2 = new StringBuilder("ja").append("va").toString();//java是一个特殊的字符串 在jdk的底层,存在很多“java”字符串
System.out.println(str2.intern()==str2);//false
}
面试题:
public static void main(String[] args) {
String str1 = new String("str") + new String("01");
str1.intern();
String str2 = "str01";
System.out.println(str1 == str2);//true
}
public static void main(String[] args) {
String s1 = new String("he") +new String("llo");
String s2 = new String("h") +new String("ello");
String s3 = s1.intern();
String s4 = s2.intern();
System.out.println(s1==s3);//true
System.out.println(s2 == s4);//false
System.out.println(s3 == s4);//true
}
-
构造方法
如果没有定义构造方法,系统将给出一个默认的无参构造方法
如果定义了构造方法,系统将不再提供默认的无参构造
-
构造方法的重载
如果自定义了带参的构造方法,还要使用无参构造,就必须手动写出无参构造
-
无论是否使用无参构造,在开发中,都推荐显示的将无参构造定义出来
-
重要功能:可以使用带参构造为成员变量进行初始化
public Student(){ // System.out.println("student的无参构造被调用..."); } public Student(String name){ this. name = name; } public Student(int age){ this.age =age; } public Student(String name , int age){ this.name = name; this.age = age; }分别使用不同的构造方法来创建对象
可以使用this(参数列表)调用本类的其他构造方法。但是要注意一点:使用this调用本类其他构造方法 必须位于构造方法的第一条语句。因此也就是说对于构造方法的调用只能调用一次。
3 标准的java bean的写法
1 成员变量 使用private修饰
2 提供getter和seter方法 来访问成员变量
3 提供构造方法:
无参的 和带有多个参数的
public class Book { //成员变量 private String title; private double price; private String author; //构造方法 public Book(){ } public Book(String title,double price , String author){ this.title = title; this.price = price; this.author = author; } //getter 和 sertter public String getTitle(){ return title; } public void setTitle(String title){ this.title = title; } public double getPrice(){ return price; } public void setPrice(double price){ this.price = price; } public String getAuthor(){ return author; } public void setAuthor(String author){ this.author =author; } } 4.常用API-String
API- Application programming Interface 应用程序编程接口
java中的API:
指的就是jdk中提供的各种功能的java类,这些类底层的实现封装了起来,我们不需要关心这些类是如何实现的,只需要学习这些类如何使用即可。
java.lang Class StringString类位于java.lang包下,凡是位于java.lang包下的类,在使用的时候,不需要导包。String类代表的是字符串。java中的所有的字符串都被实现为String类的实例。java程序中所有使用双引号引起来的字符串,都是String类的对象
4.1 String字符串的特点
1 字符串不可改变,他的值在创建之后就不能被更改
2 虽然String的值是不可变的,但是他们是可以被共享。
3 字符串效果上相当于字符数组(char[]),但是底层原理却是字节数组([byte[]])

4.2 String类的构造方法
-
String()初始化新创建的String对象,使其表示空字符序列。 -
String(char[] value)分配一个新的String,以便它表示当前包含在字符数组参数中的字符序列。 -
String(byte[] bytes)通过使用平台的默认字符集解码指定的字节数组来构造新的String。 -
String s = "abc" 直接复制的方式创建字符串abc
public static void main(String[] args) { String s1 = "aaaa";//直接赋值 String s2 = new String();//创建一个空字符串 char[] c = {'a','b','c'}; String s3 = new String(c);//字符数组 byte[] b = {97,98,99}; String s4 = new String(b);//字节数组 System.out.println("s1=" + s1); System.out.println("s2=" + s2); System.out.println("s3=" + s3); System.out.println("s4=" + s4); }4.3 创建字符串对象的两种方式的区别
4.3.1.通过构造方法创建
使用new创建字符串对象,每一次new都会申请一个内存空间,虽然内容都是相同的,但是所对应的内存地址是不同的。
char[] c = {'a','b','c'}; String s3 = new String(c);//字符数组 String ss3 = new String(c);上面的代码。jvm会首先创建一个字符数组,然后每一次new 的时候 都会有一个新的地址,只不过s3 和ss3参考的字符串的内容是相同的

4.3.2 直接赋值的方式创建
使用“”方式给出的字符串,只要字符序列相同(顺序和大小写)。无论在程序代码中出现几次,jvm都只会建立一个String对象,并在字符串常量池(String pool)中维护
java中的三种常量池:
字符串常量池 class文件常量池 运行时常量池
1 字符串常量池(又称为全局字符串池)。
jvm所使用的内存中,字符串作为一种特殊的数据类型,占据了大量的内存,且字符串有着大量的重复,由于字符串本身具有不可变性,因此使用字符串常量池对于同样的字符串可以起到一个缓存的作用,防止多次内存分配,从而提供内存的利用率
2 运行时常量池
当程序运行到某个类的时候,class文件中的信息就会被解析到内存的方法区的运行时常量池中,每个类都有一个运行时常量池。
3 class文件常量池
class常量池是在编译后每个class文件都有的,class文件中除了包含类的版本 字段 方法 接口等描述信息,还有一项信息就是常量池,用于存放编译器生成的各种字面量和符号的引用。
5 JVM内存模型

jvm从大的方面分为:堆区 栈区 方法区
栈区: 细分为java虚拟机栈 和本地方法栈
堆内存可以划分为 新生代 老年代
新生代: Eden区 from区 to区
划分出来的各个区域 分别保存不同的数据 并且在一般情况下 期采取的内存回收策略也是不同。
5.1. 堆内存
堆内存是jvm内存模型中最大的一块区域,被所有线程共享。是在jvm启动的时候进行创建。几乎所有的对象的空间分配都是在堆区来进行分配。
考虑到jvm的内存回收机制,堆内存划分为新生代和老年代两个区域(默认的新生代和老年代的空间大小比例为1:2).新生代可以在划分为Eden区,From 区(s0) to区(s1),三者的比例(8:1:1) 几乎所有的新对象的创建都是在eden区 完成。在垃圾回收(GC)过程中,Eden区的活跃的对象会被迁移到Survior区,当在达到一定的年龄(经过一定的垃圾回收算法测处理),会被转移到老年代中。
堆内存在物理上可以使不连续,但是在逻辑上需要满足连续。在实现时。可以实现成固定大小的,也可以是可扩展的。
5.2.方法区
方法区又被称为永久代,我们所讲的模型是(Hotsport最常见的jvm的模型)。同样 也是被所有的线程所共享的,该区域主要保存类的信息,静态变量,常量和编译器编译后的代码等数据
jdk7中,将永久代中的字符串常量池移动到堆中。jdk8 撤销了永久代 ,引入了元空间
方法区不需要连续的内存,可以选择固定大小或者可扩展,并且还可以选择不实现垃圾回收,相对而言,垃圾收集行为在这个区域是比较少见的,但并非数据进入方法区就如永久代的名字一样永久存在了。这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载,圾回收机制的条件是相当苛刻的。 
这段程序,以指数级不断的生成新的字符串,这样可以比较快速的消耗内存。
可以通过异常信息看到出现堆内存的异常,在jdk1.8之后,字符串常量池由永久代(方法区)转移到堆中
jvm的内存参数的设置
-
-Xms设置堆的最小空间大小。
-
-Xmx设置堆的最大空间大小。
-
-XX:NewSize设置新生代最小空间大小。
-
-XX:MaxNewSize设置新生代最大空间大小。
-
-XX:PermSize设置永久代最小空间大小。
-
-XX:MaxPermSize设置永久代最大空间大小。
-
-Xss设置每个线程的堆栈大小
public static void main(String[] args) { String s1 = "abc"; String s2 = "abc"; System.out.println(s1 == s2);//true // 使用字符数组构造一个字符串 char[] c = {'a','b','c'}; String s3 = new String(c); String s4 = new String(c); System.out.println(s3 == s4);//false String s5 = new String("abc"); String s6 = new String ("abc"); System.out.println(s5==s6);// false System.out.println(s1 == s3);//false System.out.println(s4 == s5);//false }以上对于字符串的比较使用的是== 经过分析可以知道:==比较的是两个字符串对象的引用的地址是否相同。
比较字符串的内容相同:
-
-
booleanequals(Object anObject)将此字符串与指定对象进行比较。booleanequalsIgnoreCase(String anotherString)将此String与其他String比较,忽略案例注意事项。
-
-
如果要比较两个字符串的内容是否相同 则使用equals方法
System.out.println(s1.equals(s3)); System.out.println(s4.equals(s6));System.out.println(s1.equals(s7));//false System.out.println(s1.equals(s8));//false System.out.println(s1.equalsIgnoreCase(s7));//true System.out.println(s1.equalsIgnoreCase(s8));//true遍历字符串
从键盘录入一个字符串,使用程序实现在控制台遍历该字符串。
public static void main(String[] args) { //从键盘输入一个字符串 Scanner sc = new Scanner(System.in); System.out.println("请输入您要遍历的字符串:"); String str = sc.nextLine(); // 获取数组的长度 使用数组的length属性 获取字符串的长度 使用的是String类的length方法 for(int i = 0 ; i < str.length();i++){ char c = str.charAt(i); System.out.println(c); } }统计字符的次数
键盘录入一个字符串,统计该字符串中大写字母 小写字母 数字出现的次数 (不考虑其他字符)
对于一个字符判断他是大写字母 小写字母 数字 直接判断:
大写字母: ch >= 'A' && ch<='Z'
小写字母:ch>='a'&& ch<='z'
数字:ch>='0'&&ch<='9'
public class CountCharNum { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入您要统计的字符串:"); String str = sc.nextLine(); // 定义字符统计的变量 int bigCount = 0; int smallCount = 0 ; int numberCount=0; for(int i =0 ; i < str.length();i++){ char ch = str.charAt(i); if(ch >='A'&& ch<='Z'){ bigCount++; }else if(ch >='a'&& ch<='z'){ smallCount++; }else if(ch >='0'&& ch<='9'){ numberCount++; } } System.out.println("大写字母的个数为:" + bigCount); System.out.println("小写字母的个数为:" + smallCount); System.out.println("数字的个数为:" + numberCount); } }字符串反转:
定义一个字符串,实现字符串的反转 从控制台输入abc 输出结果为cba
7 String类的常用方法
-
-
-
-
-
booleanequals(Object anObject)将此字符串与指定对象进行比较。booleanequalsIgnoreCase(String anotherString)将此String与其他String比较,忽略案例注意事项。
-
-
-
-
-
-
-
-
-
-
intlastIndexOf(int ch)返回指定字符的最后一次出现的字符串中的索引。intlastIndexOf(int ch, int fromIndex)返回指定字符的最后一次出现的字符串中的索引,从指定的索引开始向后搜索。intlastIndexOf(String str)返回指定子字符串最后一次出现的字符串中的索引。intlastIndexOf(String str, int fromIndex)返回指定子字符串的最后一次出现的字符串中的索引,从指定索引开始向后搜索。intlength()返回此字符串的长度。public static void main(String[] args) { String str = "abdcdadcd"; System.out.println(str.indexOf("a"));//0 System.out.println(str.lastIndexOf("a"));//5 } -
-
-
-
char[]toCharArray()将此字符串转换为新的字符数组。StringtoLowerCase()将所有在此字符String使用默认语言环境的规则,以小写。
-
-
-
-
-
static StringvalueOf(boolean b)返回boolean参数的字符串boolean形式。static StringvalueOf(char c)返回char参数的字符串char形式。static StringvalueOf(char[] data)返回char数组参数的字符串char形式。static StringvalueOf(char[] data, int offset, int count)返回char数组参数的特定子阵列的字符串char形式。static StringvalueOf(double d)返回double参数的字符串double形式。static StringvalueOf(float f)返回float参数的字符串float形式。static StringvalueOf(int i)返回int参数的字符串int形式。static StringvalueOf(long l)返回long参数的字符串long形式。static StringvalueOf(Object obj)返回Object参数的字符串Object形式。String s = String.valueOf(123);//将整数123 转换为字符串123
-
8 String的常见陷阱
String str1 = "abc";
String str2 = new String("abc");
字符串常量存储在字符串常量池中,并且是共享
字符串非常量对象 存储在堆中

public static void main(String[] args) {
String s1 = "hello";
String s2 = "world";
String s3 = "hello" +"world";
String s4 = s1 +"world";
String s5 = s1 + s2;
String s6 = (s1 + s2).intern();
String s7 = "helloworld";
System.out.println(s3==s4);// false
System.out.println(s3 == s7);//true
System.out.println(s3==s5);//false
System.out.println(s4==s5);//false
System.out.println(s3==s6);//true
}
-
常量与常量的拼接,结果在常量池 且常量池中不会存在相同内容的常量
-
只要其中有一个是变量,结果就在堆中。
-
如果拼接的结果调用intern(),结果就在常量池中
public static void main(String[] args) { String str1 = new StringBuilder("计算机").append("软件开发").toString(); System.out.println(str1.intern()== str1);//true String str2 = new StringBuilder("ja").append("va").toString();//java是一个特殊的字符串 在jdk的底层,存在很多“java”字符串 System.out.println(str2.intern()==str2);//false }面试题:
public static void main(String[] args) { String str1 = new String("str") + new String("01"); str1.intern(); String str2 = "str01"; System.out.println(str1 == str2);//true }public static void main(String[] args) { String s1 = new String("he") +new String("llo"); String s2 = new String("h") +new String("ello"); String s3 = s1.intern(); String s4 = s2.intern(); System.out.println(s1==s3);//true System.out.println(s2 == s4);//false System.out.println(s3 == s4);//true }
本文详细解读了Java中的面向对象三大特性:封装、继承和多态,包括封装的私有成员与get/set方法,this关键字的应用,以及构造方法的使用和内存模型。同时介绍了字符串操作、内存池与比较,以及常见陷阱和面试题涉及的内容。
75万+

被折叠的 条评论
为什么被折叠?



