7Java基础补充
1.标准Java bean写法
包括:private修饰的成员变量、getter和setter以及无参和有多个参数的有参构造方法
2.String原理
String底层是字节数组byte[]。
String不可变,但可以被共享。
3.Java中三种常量池:
(1)字符串常量池(全局字符串池):由于字符串本身具有不可变性,因此使用字符串常量池对于同样的字符串可以起到一个缓存的作用,防止多次内存分配,从而提供内存的利用率
(2)运行时常量池:当程序运行到某个类的时候,class文件中的信息就会被解析到内存的方法区的运行时常量池中,每个类都有一个运行时常量池。
(3)class文件常量池:class常量池是在编译后每个class文件都有的,class文件中除了包含类的版本 字段 方法 接口等描述信息,还有一项信息就是常量池,用于存放编译器生成的各种字面量和符号的引用。
4.细化Java内存模型
从大的方面来说,JVM内存分为几个方面:
堆内存是JVM中最大的一块区域,被所有线程共享,在JVM启动时创建。几乎所有对象的空间分配都在堆区来进行。
堆又分为新生代和老年代内存,两者的内存大小的比例大概是1:2。
新生代又分为Eden、From区和To区,三者的内存大小的比例大概是8:1:1。几乎所有新对象的内存分配都在Eden区完成。
划分不同的区,分别保存不同的数据,其内存回收策略也不相同。
在GC中,Eden区活跃的对象会被移动到survivor区,不活跃的会被GC清理掉。Survivor区中的对象达到一定的年龄,就会被移动到老年代中。
堆内存可以在物理上不连续,但是逻辑上要连续。
方法区又被称为永久代,也是被所有的线程所共享的,该区域主要保存类的信息,静态变量,常量和编译器编译后的代码等数据。
jdk7中,将永久代中的字符串常量池移动到堆中。jdk8 撤销了永久代 ,引入了元空间
方法区不需要连续的内存,可以选择固定大小或者可扩展,并且还可以选择不实现垃圾回收,相对而言,垃圾收集行为在这个区域是比较少见的,但并非数据进入方法区就如永久代的名字一样永久存在了。这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载,圾回收机制的条件是相当苛刻的。
5.字符串的比较
public static void main(String[] args) { String s1 = "abc"; String s2 = "abc"; System.out.println(s1 == s2);//true,s1指向常量池中创建的对象地址,s2指向常量池中已经存在的对象地址,这个对象是相同的 // 使用字符数组构造一个字符串 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,s1指向常量池中创建的对象地址,s3指向堆中对象 System.out.println(s4 == s5);//false,堆中不同对象 }
String str1 = "abc";//在常量池中创建对象并得到引用 String str2 = new String("abc");//在堆中创建对象并引用,然后查看常量池,此时已经有对象,所以不用再创建
public static void main(String[] args) { String s1 = "hello";//常量池中创建hello的引用 String s2 = "world";//常量池中创建world的引用 String s3 = "hello" +"world";//常量池中创建helloworld的引用 String s4 = s1 +"world";//堆中创建的对象的引用,相当于new StringBuilder(s1).append("world").toString();toString()创建一个新的堆对象。 String s5 = s1 + s2;//堆中创建对象的引用,相当于//new StringBuilder(s1).append(s2).toString();
String s6 = (s1 + s2).intern(); //该值在常量池中已经存在,返回s3的引用
String s7 = "helloworld"; //该值在常量池中已经存在,返回s3的引用
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 }
+连接字符串:
常量+常量:编译器直接优化生成结果,不需要生成StringBuilder。
常量+变量:需要生成StringBuilder,一行语句需要一个StringBuilder,append的数量基于变量和常量的个数,但当多个常量连在一起时,编译器会优化直接生成常量运算结果,算作一个append处理。
变量和变量:需要生成StringBuilder,一行语句需要一个StringBuilder,append的数量基于常量的个数
public static void main(String[] args) { String str1 = new StringBuilder("计算机").append("软件开发").toString(); System.out.println(str1.intern()== str1);//true,str1.intern()在常量池中创建一个指向str1的引用,所以相等 String str2 = new StringBuilder("ja").append("va").toString();//java是一个特殊的字符串 在jdk的底层,存在很多“java”字符串 System.out.println(str2.intern()==str2);//false,虽然没有人为创建,但是常量池中存在java对象,所以intern()返回的结果是常量池中的变量且不是ss堆对象的引用
}
public static void main(String[] args) { String str1 = new String("str") + new String("01"); str1.intern();//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 }
原文地址:https://www.cnblogs.com/Justhis610/p/15037085.html
- 【独家】手把手教线性回归分析(附R语言实例)
- 四两拨千斤:借助Spark GraphX将QQ千亿关系链计算提速20倍
- 仿微信聊天表情发送
- ASP.NET Web API对OData的支持
- 小技巧 - 简化你的泛型API
- 优化OEA中的聚合SQL
- Universal Image Loader for Android 使用实例
- 如何从 Ring Buffer 读取?
- OEA中的AutoUI重构(1) - Command自动生成
- 开源项目Universal Image Loader for Android
- android Universal Image Loader for Android 说明文档 (1)
- 修改android最小堆内存
- (转)ES6新特性概览
- 基于OEA框架的客户化设计(一) 总体设计
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- tp5递归 无限级分类详解
- PHP 进程池与轮询调度算法实现多任务的示例代码
- 如何在Laravel5.8中正确地应用Repository设计模式
- laravel框架中路由设置,路由参数和路由命名实例分析
- PHP框架实现WebSocket在线聊天通讯系统
- 设定php简写功能的方法
- 使用PHP+Redis实现延迟任务,实现自动取消订单功能
- 详解no input file specified 三种解决方法
- PHP实现微信提现功能(微信商城)
- 关于Yii2框架跑脚本时内存泄漏问题的分析与解决
- laravel 框架结合关联查询 when()用法分析
- php 实现简单的登录功能示例【基于thinkPHP框架】
- laravel框架邮箱认证实现方法详解
- 使用Git实现Laravel项目的自动化部署
- php传值和传引用的区别点总结