1. Java语言特性
- 简单
Java语法是C++语法的一个“纯净版本”,相当于对C++做了一个减法。这里没有头文件、指针运算(甚至指针 语法)、结构、联合、操作符重载、虚基类等等。不仅如此,Java开发环境远远超出大多数其他编程语言的开 发环境。
- 面相对象
在Java的世界里,一切皆对象。比如:人、狗、手机、电脑等都是对象。所谓面相对象,就是依靠对象之间 的交互来完成事情。
- 分布式(微服务)
Java有丰富的例程库,用于处理像HTTP和FTP之类的TCP/IP协议。Java应用程序能够通过URL打开和访问网络
上的对象,其便捷程度就好像访问本地文件一样。
- 健壮性
Java采用的指针模型可以消除重写内存和损坏数据的可能性,Java编译器能够 检测许多在其他语言中仅在运行时才能够检测出来的问题。
- 安全性
Java适用于网络/分布式环境。为了达到这个目标,在安全性方面投入了大量的精力。使用Java可以构建防病
毒、防篡改的系统
- 体系结构中立
编译器生成一个体系结构中立的目标文件格式,按照该中规范生成的文件,只要有Java运行时系统,这些编译后的代码就可以在许多处理器上运行。Java编译器通过生成与特定计算机体系结构无关的字节码指令来实现 这一特性。字节码不仅可以很容易的在任何机器上解释执行,而且还可以动态地翻译成本地机器代码。“Wrice once,Run anywhere”。其他语言编写的程序,在编译后如果能够严格按照字节码文件的规范生成.class文件,也可以在JVM上运行。
7.可移植性
在Java中,数据类型具有固定的大小,这消除了代码移植时的主要问题。
- 解释性
Java为了实现与平台无关,自己维护了一套基于栈架构的指令集,Java源代码经过编译之后,字节码文件中的指令就是按照自己的指令集来组织的,但是在具体硬件环境中运行时,系统并不能识别,因为Java程序在执行 时,Java解释器会逐条的将字节码文件中的指令翻译成CPU的指令集。
- 高性能
边解释边执行,垃圾回收等导致了Java代码运行效率偏低,近年来JVM也在不断的优化,比如:JIT(即时编译器),热点代码探测,让Java程序的执行效率大幅提高。
- 多线程
Java是第一个支持并发程序设计的主流语言,多线程可以带来更好的交互响应和实时行为。
- 动态性
它能够适应不断发展的环境,库中可以自由的添加新方法和实例变量,而对客户端没有任何影响。在Java中找出运行时类型信息十分简单。Java不仅仅是一门编程语言,也是一个由一些列计算机软件和规范组成的技术体系。
2. Java程序的运行
Java是一门半编译型、半解释型语言。先通过javac编译程序把源文件进行编译,编译后生成的.class文件是由字节 码组成的平台无关、面向JVM的文件。最后启动java虚拟机来运行.class文件,此时JVM会将字节码转换成平台能够 理解的形式来运行。
在运行Java程序前,必须先安装好JDK(Java Development Kit即Java开发工具包),JDK里面就包含了javac和 java工具,Java程序最终是在JVM(Java虚拟机)中运行的。
JDK、JRE、JVM之间的关系:
- JDK(Java Development Kit):Java开发工具包,提供给Java程序员使用,包含了JRE,同时还包含了编译器javac与自带的调试工具Jconsole、jstack等。
- JRE(Java Runtime Environment):Java运行时环境,包含了JVM,Java基础类库。是使用Java语言编写程 序运行的所需环境。
- JVM:Java虚拟机,运行Java代码
3. 关键字
- 用于定义访问权限修饰符:private, protected, public,default
- 用于定义类,函数,变量修饰符:abstract, final, static, synchronized
- 用于定义类与类之间的关系:extends,implements
- 用于定义建立实例及引用实例,判断实例:new,this,super,instanceof
- 用于异常处理:try,catch,finally,throw,throws
- 用于包:package,import
- 其他修饰符关键字:native,strictfp,transient,volatile,assert
4. 注释
- 单行注释:// 注释内容(用的最多)
- 多行注释:/* 注释内容*/(不推荐)
- 文档注释: /** 文档注释 */(常见于方法和类之上描述方法和类的作用),可以被javadoc工具解析,生 成一套以网页文件形式体现的程序说明文档
- 多行注释不能嵌套使用
- 不论是单行还是多行注释,都不参与编译,即编译之后生成的.class文件中不包含注释信息。
5. 标识符
在程序中由用户给类名、方法名或 者变量所取的名字。
由数字,字母,下划线,美元符号组成,
不能以数字、关键字开头,且严格区分大小写。
建议 :
- 类名 :每个首字母大写(大驼峰)
- 方法名:首字母小写,后面每个字母的首字母大写(小驼峰)
- 变量名:首字母小写,后面每个字母的首字母大写(小驼峰)
6. 字面常量
常量即程序运行期间,固定不变的量称为常量
示例:
System.Out.println("Hello World");
不论程序何时运行,输出的都是Hello World,其实"Hello World"就是字面常量。
6.1 字面常量的分类
- 字符串常量:由""括起来的,比如“12345”、“hello”、“你好”。
- 整形常量:程序中直接写的数字(注意没有小数点),比如:100、1000 。
- 浮点数常量:程序中直接写的小数,比如:3.14、0.49。
- 字符常量:由 单引号 括起来的当个字符,比如:‘A’、‘1’。
- 布尔常量:只有两种true和false。
- 空常量:null。
7. 数据类型
7.1 四类基本数据类型
整型,浮点型,字符型,布尔型
7.1.1 八种
byte,short,int,long,float,double,char,boolean。
- 不论是在16位系统还是32位系统,int都占用4个字节,long都占8个字节
- 整形和浮点型都是带有符号的
- 整型默认为int型,浮点型默认为double
字节是计算机中表示空间大小的基本单位.
计算机使用二进制表示数据. 我们认为 8 个二进制位(bit) 为一个字节(Byte). 我们平时的计算机为 8GB 内存, 意思是 8G 个字节.其中 1KB = 1024 Byte, 1MB = 1024 KB, 1GB = 1024 MB.所以 8GB 相当于 80 多亿个字节.
7.2 引用数据类型String
7.2.1 String类的构造方式:
使用常量串构造:
直接newString对象:
使用字符数组进行构造:
String是引用类型,内部并不存储字符串本身,在JDK1.8中,字符串实际保存在char类型的数组中。在Java中“”引起来的也是String类型对象。
7.2.1.1 字符串常量池:
为了节省存储空间以及程序的运行效率,Java中引入了:
- Class文件常量池:
每个.Java源文件编译后生成.Class文件中会保存当前类中的字面常量以及符号信息。- 运行时常量池:
在.Class文件被加载时,.Class文件中的常量池被加载到内存中称为运行时常量池,运行时常量池每个类都有一份。- 字符串常量池:
字符串常量池在JVM中是StringTable类,实际是一个固定大小的HashTable在堆中 ,大小可设置,有范围限制,最小是1009。
7.2.1.2 String对象创建的区别:
- 直接使用字符串常量进行赋值:
在字节码文件加载时,常量串已经加载好了并保存在字符串常量池中,创建对象时,先在字符串常量池中找,将字符串引用赋值给对象。使用常量串创建String类型对象的效率更高,而且更节省空间,也可以将创建的字符串对象通过 intern 方式添加进字符串常量池中。 - 通过new创建String类对象:
只要是new的对象,都是唯一的。
- String str = “hello”:
只会开辟一块堆内存空间,保存在字符串常量池中,然后str共享常量池中的String对象。- String str = new String(“hello”):
会开辟两块堆内存空间,字符串"hello"保存在字符串常量池中,然后用常量池中的String对象给新开辟的String对象赋值。- String str = new String(new char[]{‘h’, ‘e’, ‘l’, ‘l’, ‘o’}):
先在堆上创建一个String对象,然后利用copyof将重新开辟数组空间,将参数字符串数组中内容拷贝到String对象中。
7.2.1.3 字符串的不可变性:
String是一种不可变对象. 字符串中的内容是不可改变。
String类中的字符实际保存在内部维护的value字符数组中,而且String类被final修饰表明该类不能被继承,value被修饰被final修饰表明value自身的值不能改变,即不能引用其它字符数组,但是其引用空间中的内容可以修改。
final修饰类表明该类不想被继承,final修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象中的内容是可以修改的。所有涉及到可能修改字符串内容的操作都是创建一个新对象,改变的是新对象。
7.2.1.3.1 为什么 String 要设计成不可变的?
- 方便实现字符串对象池. 如果 String 可变, 那么对象池就需要考虑写时拷贝的问题了.
- 不可变对象是线程安全的.
- 不可变对象更方便缓存 hash code, 作为 key 时可以更高效的保存到 HashMap 中
7.2.2 String对象的比较:
-
==
比较是否引用同一个对象(对于内置类型,== 比较的是变量中的值;对于引用类型 == 比较的是引用中的地址)。 -
boolean equals(Object anObject) 方法
按照字典序(字符大小的顺序)比较。先检测this 和 anObject 是否为同一个对象比较,如果是返回true,检测anObject是否为String类型的对象,如果是继续比较,否则返回false,将anObject向下转型为String类型对象,this和anObject两个字符串的长度是否相同,是继续比较,否则返回false,按照字典序,从前往后逐个字符进行比较。 -
int compareTo(String s) 方法
按照字典序进行比较:1. 先按照字典次序大小比较,如果出现不等的字符,直接返回这两个字符的大小差值,2. 如果前k个字符相等(k为两个字符长度最小值),返回两个字符串长度差值。 -
int compareToIgnoreCase(String str) 方法:与compareTo方式相同,但是忽略大小写比较。
7.2.3 字符串查找:
- char charAt(int index):返回index位置上字符,如果index为负数或者越界,抛出IndexOutOfBoundsException异常。
- int indexOf(int ch) :返回ch第一次出现的位置,没有返回-1。
int indexOf(int ch, int fromIndex):从fromIndex位置开始找ch第一次出现的位置,没有返回-1。 - int indexOf(String str):返回str第一次出现的位置,没有返回-1。
- int indexOf(String str, intfromIndex):从fromIndex位置开始找str第一次出现的位置,没有返回-1。
- int lastIndexOf(int ch):从后往前找,返回ch第一次出现的位置,没有返回-1。
- int lastIndexOf(int ch, int fromIndex):从fromIndex位置开始找,从后往前找ch第一次出现的位置,没有返回-1。
int lastIndexOf(String str) :从后往前找,返回str第一次出现的位置,没有返回-1。 - int lastIndexOf(String str, int fromIndex):从fromIndex位置开始找,从后往前找str第一次出现的位置,没有返回-1。
7.2.4 转化:
- 数值和字符串转化:Integer.parseInt()Double.parseDouble()……
- 大小写转换:toUpperCase(),toLowerCase()。
- 字符串转数组:toCharArray(),
- 数组转字符串:new String(ch)
- 格式化:format(“%d-%d-%d”, 2019, 9,14)
7.2.5 替换:
- 替换所有的指定内容:String replaceAll(String regex, String replacement)
- 替换首个内容:String replaceFirst(String regex, String replacement)
由于字符串是不可变对象, 替换不修改当前字符串, 而是产生一个新的字符串。
7.2.6 字符串拆分:
- 将字符串全部拆分:String[] split(String regex)
- 将字符串以指定的格式,拆分为limit组:String[] split(String regex, int limit)
字符"|“,”*“,”+“都得加上转义字符,前面加上 “\” .
而如果是 “” ,那么就得写成 “\\” .
如果一个字符串中有多个分隔符,可以用”|"作为连字符.
7.2.7 字符串截取:
- 从指定索引截取到结尾:String substring(int beginIndex)
- 截取部分内容:String substring(int beginIndex, int endIndex) 注意前闭后开区间的写法, substring(0, 5) 表示包含 0 号下标的字符, 不包含 5 号下标
7.2.8 字符串修改:
尽量避免直接对String类型对象进行修改,因为String类是不能修改的,所有的修改都会创建新对象,效率非常低下,如果要修改建议尽量使用StringBuffer或者StringBuilder。
7.2.8.1 String和StringBuilder类转换。
- String变为StringBuilder: 利用StringBuilder的构造方法或append()方法。
- StringBuilder变为String: 调用toString()方法。
7.2.8.2 String、StringBuffer、StringBuilder的区别:
- String的内容不可修改,StringBuffer与StringBuilder的内容可以修改。
- StringBuffer与StringBuilder大部分功能是相似的。
- StringBuffer采用同步处理,属于线程安全操作;而- StringBuilder未采用同步处理,属于线程不安全操作。
7.2.9 其他方法
- 去掉字符串中的左右空格,保留中间空格:String trim() ,trim 会去掉字符串开头和结尾的空白字符(空格, 换行, 制表符等)
- 字符串转大写:String toUpperCase()
- 字符串转小写:String toLowerCase()
8. 枚举类型
在Java当中枚举实际上就是一个类,将常量组织起来统一进行管理,是 java.lang.Enum 的子类,也就是说,自己写的枚举类,就算没有显示的继承 Enum ,但是其默认继承了这个类。枚举的构造方法默认是私有的。枚举常量更简单安全 。 枚举具有内置方法 ,代码更优雅,但是不可继承,无法扩展。应用场景:错误状态码,消息类型,颜色的划分,状态机等等…
Enum 类的常用方法:
以数组形式返回枚举类型的所有成员values() ;获取枚举成员的索引位置ordinal() ;将普通字符串转换为枚举实例valueOf() ;比较两个枚举成员在定义时的顺序compareTo()。
9. 变量
有些内容可能会经常改变,在Java程序中,称为变量,数据类型就是用来定义不同种类变量的。
9.1 语法格式
数据类型 变量名 = 初始值;
示例:
int a = 10; // 定义整形变量a,a是变量名也称为标识符,该变量中放置的值为10
double d = 3.14;
char c = 'A';
boolean b = true;
9.2 整型(int)变量
- int不论在何种系统下都是4个字节
- 如果没有合适的初始值,可以设置为0
- 在给变量设置初始值时,值不能超过int的表示范围,否则会导致溢出
- 变量在使用之前必须要赋初值,否则编译报错
- int的包装类型为 Integer
9.3 长整型(long)变量
- 长整型变量的初始值后加L或者l,推荐加L
- 长整型不论在那个系统下都占8个字节
- 长整型的表示范围为: ~
- long的包装类型为Long
9.4 短整型(short)变量
- short在任何系统下都占2个字节
- short的表示范围为:-32768 ~ 32767
- 使用时注意不要超过范围(一般使用比较少)
- short的包装类型为Short
9.5 字节型(byte)变量
- byte在任何系统下都占1个字节
- byte的范围是:-128 ~ 127
- 字节的包装类型为Byte
9.6 双精度浮点型(double)变量
- double在任何系统下都占8个字节
- 浮点数与整数在内存中的存储方式不同,不能单纯使用 的形式来计算
- double的包装类型为Double
- double 类型的内存布局遵守 IEEE 754 标准(和C语言一样), 尝试使用有限的内存空间表示可能无限的小数, 势
必会存在一定的精度误差,因此浮点数是个近似值,并不是精确值。 - 在 Java 中, int 除以 int 的值仍然是 int(会直接舍弃小数部分)。如果想得到 0.5, 需要使用 double 类型计算.
9.7 单精度浮点型(float)变量
float 类型在 Java 中占四个字节, 同样遵守 IEEE 754 标准. 由于表示的数据精度范围较小, 一般在工程上用到浮点数 都优先考虑 double, 不太推荐使用 float. float的包装类型为Float。
9.8 字符型(char)变量
- Java 中使用 单引号 + 单个字母 的形式表示字符字面值.
- 计算机中的字符本质上是一个整数. 在 C 语言中使用 ASCII 表示字符, 而 Java 中使用 Unicode 表示字符. 因此 一个字符占用两个字节, 表示的字符种类更多, 包括中文.
- char的包装类