Java语法
jvm 和 jre 相关
Java 语言编译过程
Java代码编译:是由Java源码编译器来完成;
Java字节码的执行:是由JVM执行引擎来完成
Java程序从源文件创建到程序运行要经过两大步骤:
1、源文件由编译器编译成字节码(ByteCode)
2、字节码由java虚拟机解释运行。因为java程序既要编译同时也要经过JVM的解释运行,所以说Java被称为半解释语言( "semi-interpreted" language)
写这段代码,编译会过,但是 jvm 会找不到 main 入口
任何一个class一定要有 main 方法
命令行参数
Java 命令行参数String []args
,args[0]
是第一个参数,不储存程序名字。
标志符
变量
在Java中,不区分变量的声明与定义
初始化
局部变量不初始化使用,编译错误
但是static变量在全局,会初始化
变量 type casting
- byte 8位 1个字节
- char 16位 2个字节
- short 16位 2个字节
- int 32位 4个字节
- float 32位 4个字节
- double 64位8个字节
- long 64位 8个字节
- boolean 8位 1个字节
多个byte的变量都是用 big endian 储存的
变量如果被赋值,超过所能够接受的范围,如:char c = 1000;
就编译错误
浮点数默认是double,**<font style="color:#DF2A3F;">1.2f</font>**
或者**<font style="color:#DF2A3F;">1.2F</font>**
表示float
Java不支持自动强制类型转换,如果需要,必须由程序显式进行强制类型转换。如上面的int x = 5/2.0;
应该写成int x = (int)(5/2.0)
赋值float
需要float a=1.0f
,long
需要long a = 1L
注意后缀!
常量声明用 final
final 用法
- 修饰单个变量
但是如果final修饰数组,则数组里面的元素的值可以被改变
- 修饰method
表示一个函数不可更改,也就是不能被overload,而不是修饰返回值的
- 修饰class
表示整个类不能被继承了,自然,里面的所有方法也相当于被加了final。
- 不能修饰interface
输入输出
console
输入
输出
printf不按照格式来,编译能过但是运行挂
file
switch
只能对String int short byte char
选择
Math class
舍入
ceil
天花板,向上取,floor
地板,向下取
rint
x is rounded to its nearest integer. If x is equally close to two integers, the even one is returned as a double.
random()
Math.random()
左闭右开[0,1)
Character class
注意这些都有返回值,要改变某个变量的值,需要char c = toLowerCase(c);
而不是toLowerCase(c);
String class
比较
子串处理
substring(begin,end)
左闭右开[begin,end)
正则表达式匹配字符串
TODO
.format()方法
TODO
String.valueOf()方法
TODO
一维数组
Java数组分配在堆上
命令行参数,带有String[] args在java中,args[0]是第一个参数,程序名没有存储在args中
只声明
只创建
创建完数组后有默认初始值
声明+创建
初始化
copy
Arrays.binarySearch Method
- 找到,返回下标
- 找不到,返回:
-被查找元素本应该出现的下标-1
Arrays.sort Method
匿名数组
函数返回一个数组
多维数组
只声明
只创建
声明+创建
初始化
length
matrix.length 是行数量
Java 面向对象
类 class
一个Java源文件,可以包含多个类,但是只能包含一个公共类。
Java 中用变量定义状态,用方法定义行为
- Java 中的类也有构造函数,在对象构造的时候调用,但是对象的定义也可以不需要构造函数,当类定义里没有显式声明的构造函数时Java 编译器会自动调用一个default constructor
- Java 中方法和成员变量的引用方式:objectRefVar.methodName(arguments)
– Reference Data Fields 有默认值
∗ String 类型是null,数值类型是0,布尔类型是false,char 类型是\u0000 ,但是Java 对于方法中的局部变量不会赋予默认值
∗ 比如int x
后直接对其进行print 会发生编译错误,因为变量没有初始化
main 方法
在Java中,main()
方法是Java应用程序的入口方法,也就是说,程序在运行的时候,第一个执行的方法就是main()
方法,这个方法和其他的方法有很大的不同,比如方法的名字必须是main
,方法必须是public static void
类型的,方法必须接收一个字符串数组的参数等等。
instance 和staic——和C++ 相同
- instance 是变量的实例,instance variable 属于特定的实例,instance method 由类的一个实例调用
- static 类型的变量和方法被一个类的所有成员共享
值传递和引用传递
Passing by value for primitive type value (the value is passed to the parameter)
Passing by value for reference type value (the value is the reference to the object)
- Java 本质上是一种值传递
这个程序无法交换a和b的值。因为只是拷贝了a和b的引用,在<font style="color:#DF2A3F;">swap</font>
函数里面对引用进行交换。
- 对象中的一个数组实际上是一个reference variable 的数组
- https://www.cnblogs.com/ming-szu/p/9165393.html Java对object数组排序 特别注意lambda表达式,上机考试可以用
package相关的访问权限
By default, the class, variable, or method can be accessed by any class in the same package
private
修饰:只能单个class内部访问没有修饰:能在单个package里访问
public
修饰:所有都可以访问
import package注意事项
import
不会递归,只会引入当前package下的直接类。
比如 import java.util.*
,只会引入java.util
下的直接类,而不会引入java.util
下嵌套包的类,如不会引入java.util.zip
下的类。试图嵌套引入的形式也是无效的,如import java.util..
- import不仅可以导入类,还可以导入静态方法和静态域。
比如:import static java.lang.System.*
;就可以使用System类的静态方法和静态域了。 out.println(“Hello World!”); //System.out
exit(0); //System.exit
- 需要将类文件切实安置到其所归属之Package所对应的相对路径下。
package com.horstmann.core
public class Employee{...}
,需要将Employee.java放到com/horstmann/core
目录下,编译器也会将class文件放到相同的目录结构中
不可变类
final
class / 让类的所有构造器都变为私有的或包级私有的,并添加公共的静态工厂来代替公有的构造器。- 所有数据域都是
private
- 没有
set
方法,对象的引用不会泄露
初始化
总结起来说,java中数据成员的初始化过程是:
①先默认初始化
②进行定义处的初始化(指定初始化)
③构造函数初始化
装箱
autoboxing
Numeric Wrapper Class--BigInteger & BigDemical
.valueOf() 方法 与 .intVaule()
valueOf会调用缓存机制(如果有实现),并且返回一个object
.toString()方法
<font style="color:rgb(0, 0, 0);">public int compareTo(BigDecimal val)</font>
比较大小(仅比较两个BigDecimal对象数值是否相等,忽略精度;大于则返回正数,小于则返回负数,等于返回0)
<font style="color:rgb(0, 0, 0);">public BigDecimal max(BigDecimal val)</font>
返回较大值
常量池
例子:
结果应该如下:
java中基本类型的包装类的大部分都实现了常量池技术,这些类是Byte,Short,Integer,Long,Character,Boolean
两种浮点数类型的包装类则没有实现。
Byte,Short,Integer,Long,Character这5种整型的包装类也只是对从-128 到127的对象使用对象池,也即对象不负责创建和管理大于127和小于-128的这些类的对象。利用缓存机制实现常量池:为了减少不必要的内存消耗和内存开辟次数,Integer 里做了一个缓存,缓存了从-128 到127 之间的Integer 对象,总共是256个对象。
结果应该如下:
区分原始数据类型和类
浮点数包装类没有实现缓存
枚举类
采用enum
关键字定义,所有的枚举类型都继承自Enum
类型,通常常量用public final static
来定义,在枚举类中可以用如下方式定义
枚举类的特性
- 枚举类是
final
,不能被继承 - 含有
values()
的静态方法,可以按照声明顺序返回其值数组 ordinal()
方法,返回枚举值在枚举类中的顺序,根据声明时候的顺序决定(从0开始)- 用
valueOf()
来得到枚举实例,toString()
将枚举转化为可以打印的字符串 - 枚举类型支持switch
输出结果解释:
- 星期.天.名 输出了枚举常量
天
的属性名
,即 "星期天"。 - 星期.天 输出了枚举常量
天
的名字,即 "天"。 - 天.名 输出了枚举常量
天
的属性名
,即 "星期天"。 - 天 输出了枚举常量
天
的名称,即 "天"。
• Java 的枚举本质上是int 值
–
在枚举类加入方法,域
在枚举类中,可以将不同的行为与每个常量关联起来。例如,对于Operation中的PLUS, MINUS, TIMES和DIVIDE,有不同的操作。
改一下:
程序填空
继承
Java 中继承的关键词是extends
super()
:
- 子类没有继承基类的构造函数,但是子类中可以用关键字super 去调用基类的构造函数
父类有无参构造器,子类才可以写无参构造器;父类有含参构造器,子类才可以写含参构造器.
下面的执行顺序是,先执行父类A
,先去执行int i
的构造,再执行A的无参,再执行B的i,最后B的无参。同名的函数使用的是B的。
B继承了A,但是B的构造里面没有调用A的构造
TODO override 和 继承的区别