开篇先放下我的Github地址:masuo777.github.io/ 欢迎访问!!!
Java基础技术
Java最核心的一直将是Java基础,不论你的框架如何,Java的基础才是建立起实用的框架的核心。
Java概述
首先,来重新过一遍自己学习Java最开始那一段快乐的时光,以及自己没来得及了解的我们所不太了解的Java,这一次让我们一起揭开Java的神秘面纱。
什么是Java?
Java是sun公司在1995年发布的编程语言和计算平台。Java作为编程语言是我们众所周知的,那么作为计算平台的Java语言你了解多少呢。
想想Java与其他语言有啥区别:Java开发是跨平台的。
计算平台是计算机系统硬件与软件的设计和开发的基础。具有一定的标准性和公开性,同时也决定了该计算机系统的硬件与软件的性能。了解即可。
Java主要分为三个版本:
J2SE:Java2 Platform Standard Edition,java平台标准版,支持在大多数环境下适用Java应用程序,为以下两位提供基础服务。
J2EE:Java2 platform Enterprise Edition,Java平台企业版,企业版,强大,完整,健壮。
J2ME:Java2 platform Micro Edition,Java平台微型版,主要为微型机器及嵌入式设备提供运行环境。
我们经常用的是SE版本,也可以用到EE,看个人需求。
Java的特点
- 面向对象,这里来复习一下面向对象与面向过程开发的区别。
首先有的是面向过程开发,以过程为中心,解决一个问题需要哪些过程,针对过程去开发,比如1+1,首先输入第一个数字,然后输入运算符,然后输入第二个运算符,最后计算结果,然后输出结果,代表语言是C。
其次是面向对象开发,简称OOP,面向对象是以对象为中心,代表语言是C++,Java。
这两个开发方式的区别具体可以参考:www.zhihu.com/question/27…
这个作者解释的生动形象,而且非常容易理解,还提供了面试见解。
- 无指针,不用手动管理对象的生命周期,指针一直是c语言中最难的那部分,也是最为劝退新手的部分,在Java中完全不用担心指针的问题。
- 静态语言开发,静态语言主要有Pascal, Perl, C/C++, JAVA, C#, Scala等
- 跨平台性,这是Java最受欢迎的原因了吧,Java的跨平台性,让他在多个操作系统中畅通无阻的执行,而实现Java跨平台的原因就是jvm,这也是Java最核心的部分。
Java开发环境
JDK
包含Java的运行环境以及开发环境。适合开发人员开发时使用。
JRE
只包括Java的运行环境,以及部分Java的基础库。适合在项目完成之后,搭建项目时使用。
接下来进入正题。
数据类型
基本类型
Java有8种基本类型,分为整形(短整型,整型,长整型),浮点型(double,float),布尔类型(boolean),字符型(byte,char)
- byte/8位
- char/16位
- short/16
- int/32
- float/32
- double/63
- long/64
- boolean/
boolean只有两个值,true/false,没有明确的大小,jvm在编译时期为了方便,将Boolean转成int类型,因为1bit没有独立地址,而int有(byte也有)。
包装类型(封装类)
每个基础类型都会对应一个封装类,基础类型与其对应的包装类型之间的赋值使用自动装箱与拆箱完成。
Integer i = 2;//装箱,将基础类封装起来,叫装箱。调用了Integer.valueOf(2)
int j = i;//拆箱,与之对应的就是拆箱。调用了X.intValue()
缓存池
new Integer(123)
Integer.valueOf(123)
//看看这两个声明类型的区别
以上两者的区别在于:
//new Integer(123)每次都会创建一个新的对象
//Integer.valueOf(123)会使用缓冲池中的对象,对此调用会取得同一个对象的引用
//实例
Integer x = new Integer(123);
Integer y = new Integer(123);
System.out.println(x==y);//false
Integer i = Integer.valueOf(123);
Integer j = Integer.valueOf(123);
System.out.println(i==j);//true
基本类型对应的缓存池如下:
- boolean :true/false
- byte :all bytes
- short/int : -128 ~127
- char : \u0000(第0个) ~ \u007F(第127个)
字符串String
概览
String被升为final,因此String是不可继承的(包括其他封装类)。
在Java8中,String使用char数组存储数据。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
}
在Java9中,String使用byte数组存储数据,同时使用coder来标识使用了那种编码。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final byte[] value;
/** The identifier of the encoding used to encode the bytes in {@code
value}. */
private final byte coder;
}
在以上源码中可以看到String的char/byte数组都被声明为了final,所以意味着数组在声明之后就是不能变得,也就是说String声明后是不可变的。
声明为final的优点:
- 缓存hash值,
因为String的hash值经常被调用,如hash map中的key值经常是String,String的不可变性,使得hash值也不会变,因此只需一次计算。
- String Pool的需要
如果一个String被创建过了,那么就会从String pool 中取得引用,只有String是不可变的,才能使用String pool。
- 安全性
String 经常作为参数,String 不可变性可以保证参数不可变。例如在作为⽹络连接参数的情况下如果 String 是可变的,那么在⽹络连接过程中,String 被改变,改变 String 的那⼀⽅以为现在连接的是其它 主机,⽽实际情况却不⼀定是
- 线程安全
在多个线程中String值仍保持不变,使得在线程中可以安全的使用String。
String ,String buffer ,String Builder
- 可变性
String 不可变,String buffer和String builder可变
- 线程安全(security)
String不可变,所以是线程安全的,
String buffer是线程不安全的
String builder是线程安全的,内部使用synchronized(锁)同步
String pool
与缓存池功能类似,用来保存着所有字符串字面量,这些字面量在编译时期就确定了。不仅如此,还可以使用String的intern()方法在运行过程将字符串添加到String pool。
这里引入了一个字符串字面量的定义:字符串字面量即指声明的String类型双引号之间的常量,如“stir”中的stir。
当一个字符串调用intern()方法时,如果String pool中已经存在一个字符串和该字符串值相等(值相等要用.equals()来判断),那么就会返回String pool中字符串的引用;否则,就会在String pool中添加一个新的字符串,并返回这个字符串的引用。
使用new新建字符串是不同的两个字符串,使用intern()方法创建的对象是对同一个字符串的引用。
String s1 = new String("123");
String s2 = new String("123");
System.out.println(s1==s2);//false
String s3 = s1.intern();
String s4 = s2.intern();
System.out.println(s3==s4);//true
使用赋值的方式创建对象时,都是从String pool中引用对象,所以他们都是相等的。
String s5 = "555";
String s6 = "555";
System.out.println(s5==s6);//true
在Java7之前,String pool存放在运行时常量池中,他属于永久代,而在Java7之后,将String pool移到了堆中,这是因为永久代的空间有限,在大量使用字符串的场景下会报Out of memory的错误。
注意:
//使用new 新建字符串会新建两个字符串(前提是String pool中不存在与新建变量值相等的对象),
Java new一个对象的过程
参考:zhuanlan.zhihu.com/p/339839277 ,这是个人觉的还算能看懂的一篇。
一看到new这个关键字,我们脑海里应该是,他在Java的堆内存中开辟了一块空间。
过程过于复杂,简单来说,就是以下几个步骤,
- 当虚拟机收到一条new指令时,首先检查这个指令的参数能否在常量池中定位到一个类的符号引用,然后检查这个类是否被加载解析,初始化,即验证是否第一次使用这个类,如果不是第一次使用则需要先执行对应类的加载过程,
声明
String 变量名 = 变量值;双引号
String s = “string”;
charAt用法
charAt是根据下表取出字符串中对应的字符的一种方法:字符串名称.charAt(字符下标)
String s = "String";
for(int i = 0;i<=5;i++){
System.out.println(s.charAt(i));
}
//输出:S t r i n
在字符串后面加字符串或字符
使用‘+=’即可,string1+=string2/
String s1="aaa";
String s2="bbb";
String s3=s1+s2;
//s3="aaabbb"
foreach的使用
只能针对数组类型的变量进行遍历输出等操作:for(类型 变量名:数组名)
String []arr = {"aaadd","aaasss","aaaaaa"};
for(String s:arr){
System.out.println(s);
}
//输出:aaadd aaasss aaaaaa