java学习随记
Java简介
Java最早是由SUN公司(已被Oracle收购)的詹姆斯·高斯林(高司令,人称Java之父)在上个世纪90年代初开发的一种编程语言,最初被命名为Oak,目标是针对小型家电设备的嵌入式应用,结果市场没啥反响。谁料到互联网的崛起,让Oak重新焕发了生机,于是SUN公司改造了Oak,在1995年以Java的名称正式发布,原因是Oak已经被人注册了,因此SUN注册了Java这个商标。随着互联网的高速发展,Java逐渐成为最重要的网络编程语言。
Java介于编译型语言和解释型语言之间。
随着Java的发展,SUN给Java又分出了三个不同版本:
- Java SE:Standard Edition
- Java EE:Enterprise Edition
- Java ME:Micro Edition
简单来说,Java SE就是标准版,包含标准的JVM和标准库,而Java EE是企业版,它只是在Java SE的基础上加上了大量的API和库,以便方便开发Web应用、数据库、消息服务等,Java EE的应用使用的虚拟机和Java SE完全相同。
名词解释:
JDK:Java Development Kit
JRE:Java Runtime Environment
1
JRE就是运行Java字节码的虚拟机。但是,如果只有Java源码,要编译成Java字节码,就需要JDK,因为JDK除了包含JRE,还提供了编译器、调试器等开发工具。
JSR规范:Java Specification Request
JCP组织:Java Community Process
1
JSR是一系列的规范,从JVM的内存模型到Web程序接口,全部都标准化了。而负责审核JSR的组织就是JCP。
Java注释
单行注释
1 | // 注释内容 |
多行注释
1 | /* |
javadoc注释,可被javadoc.exe解析为java帮助文档。
1 | /** |
第一个代码说明
1 | // public 表示公开的 |
public class 和 class的区别
- 一个java源文件中可以定义多个class
- 一个java源文件中public class不是必须的
- 一个java源文件中若定义多个class,编译后每一个class会生成相应的xxx.class字节码文件
- 一个java源文件中如定义public class类,只能有一个,名字和文件名相同
- 每一个class中都可以编写main方法,都可以设定程序的入口
- 在调用
java xxx
时,xxx中须有主方法public static void main(String [] args)
。
标识符
什么是标识符
用于表示类名、方法名、变量名、接口名、常量名等有效字符的组合。
标识符的命名规则
- 只能由数字、字母、下划线(_)和美元符号($)组成
- 不能以数字开头
- 严格区分大小写
- 关键字不能做标识符
- 理论上长度不限制,但不要太长
标识符的命名规范
- 见名知意
- 遵守驼峰命名方式
- 类名、接口名:采用大驼峰
- 变量名、方法名:采用小驼峰
- 常量名:采用全部大写
关键字
https://www.cnblogs.com/chenglc/p/6922834.html
java语言的变量
什么是变量
- 变量是指向内存中的一块空间,这块空间有
数据类型
、名字
和字面值
- 变量包括三部分:数据类型、名字和字面值
- 变量是内存中数据存储的最基本单元
数据类型的作用
- 不用的数据有不同的数据类型,不同的数据类型底层会分配不同大小的空间
- 数据类型是程序在运行期间应该分配多大的内存空间
变量的要求
变量中存储的数据必须和其对应的数据类型一致,否则编译出错。
变量的声明和赋值
声明
1 | 数据类型 变量名; |
示例:
1 | int age; |
赋值
1 | 变量名 = 字面值; |
初始化并赋值
1 | 数据类型 变量名 = 字面值; |
1 | int age = 25; |
示例:
1 | public class Variable{ |
变量的分类
根据变量声明的位置
- 局部变量:方法体中的变量
- 成员变量:类体中的变量
1 | public class Variable{ |
java语言的数据类型
数据类型的作用
JVM在运行程序的时候根据数据类型来分配内存空间
数据类型分类
- 基本数据类型
- 整数型(byte, short, int, long)
- 浮点型(float, double)
- 布尔型(boolean)
- 字符型(char)
- 引用数据新类型
- 字符串(string)
八种基本数据类型各自占用的空间大小及默认值
1 | 基本数据类型 占用空间大小(Byte) 默认值 |
char数据类型
语法
1 | public class DataTypeChar{ |
转译字符
转义字符 | 意义 | ASCII码值(十进制 |
---|---|---|
\b | 退格(BS) ,将当前位置移到前一列 | 008 |
\f | 换页(FF),将当前位置移到下页开头 | 012 |
\n | 换行(LF) ,将当前位置移到下一行开头 | 010 |
\r | 回车(CR) ,将当前位置移到本行开头 | 013 |
\t | 水平制表(HT) (跳到下一个TAB位置) | 009 |
\v | 垂直制表(VT) | 011 |
\ | 代表一个反斜线字符’’' | 092 |
' | 代表一个单引号(撇号)字符 | 039 |
" | 代表一个双引号字符 | 034 |
\0 | 空字符(NULL) | 000 |
\ddd | 1到3位八进制数所代表的任意字符 | 三位八进制 |
\uhhhh | 1到2位十六进制所代表的任意字符 | 二位十六进制 |
整数型
java整数型默认为int
型,若要使用长整形,数字后加上l
或L
。
java语言整数型字面值有三种表现形式
- 十进制:缺省默认方式
- 八进制:数字以
0
开头 - 十六进制:数字以
0x
开头
示例:
1 | public class DataTypeTest{ |
类型转换
java中整数型默认为
int
,占4个字节。1
2
3
4// 声明数据类型为int的变量a
// 将数据类型为int的100字面值复制给变量a
// 这里不存在数据类型转换
int a = 100;1
2
3
4
5// 声明数据类型为 long 的变量 b
// 将数据类型为int的100字面值复制给变量b
// 这里存在数据类型转换
// 小容量赋值给大容量,程序不会报错
long b = 100;1
2long c = 100L;
int d = c; // 大容量数据赋值给小容量数据,编译出错强制类型转换原理
1
2
3
4
5long c = 100L;
int d = (int)c;
//long 100L --> 0000000 0000000 0000000 0000000 0000000 0000000 0000000 01100100
//int 100 --> 0000000 0000000 0000000 01100100
浮点型
java中浮点型默认为double
型。
1 | float f1 = 5.1f |
布尔型
在java中,boolean型只有true
和false
两个值。
1 | boolean flag = true; |
基本数据类型转换规则
基本类型中除boolean类型外,其它7种类型之间都可以转换。
小容量向大容量转换称为自动类型转换,容量从小到大排序:
byte < short / char < int < long < float < double
大容量转换为小容量称为强制类型转换,需要加强制类型转换符,可能会损失精度。
当整数字面值没有超过byte、short、char的取值范围,可直接赋值
byte、short、char混合运算时,先各自转换成int类型再做运算。
多种数据类型混合运算时,先转换成容量最大的那个再做运算。
运算符
算数运算符
1 | /* |
关系运算符
1 | public class OperatorTest{ |
逻辑运算符
1 | /* |
赋值运算符
1 | /* |
1 | byte a = 10; |
注:扩展类的赋值运算符不改变数据类型
字符串连接运算符
1 | /* |
三目运算符
1 | 布尔表达式 ? 值一 : 值二 |
1 | char sex = true ? '女' : '男'; |
控制语句
选择语句
1 | if |
if 语法
1 | if(布尔表达式){ |
1 | if(布尔表达式){ |
1 | if(布尔表达式){ |
示例:
1 | public class TestIf{ |
switch语句
语法
1 | switch(int or String字面值或变量:){ |
switch case合并
1 | switch (int or String){ |
注意事项
switch后只能是
int
或String
,不能是别的1
2
3
4
5
6
7
8
9public class SwitchTest{
public static void main(String [] args){
long num = 10L;
switch (num){ // 编译出错,num是long类型,要求是int类型
case 10:
System.out.println("10");
}
}
}switch后若是
char
类型,最后会转换为int
类型,在进行匹配。1
2
3
4
5
6
7
8
9
10public class SwitchTest{
public static void main(String [] args){
char a = 'a';
switch(a){
case 97:
System.out.println("a is 97");
break;
}
}
}
示例
1 | public class SwitchTest{ |
循环语句
1 | for |
for循环
1 | public class ForTest{ |
示例
打印 9*9 乘法表
1 | // 打印 9*9 乘法表 |
打印 1000内的质数,每8个显示一行
1 | public class ForTest{ |
while / do … while循环
1 | public class WhileTest{ |
控制循环语句
1 | break |
break语句
break是java中的关键字
break;
是一个完整的语句break语句用在
switch
语句、循环语句等当中用来终止程序的执行break语句默认终止当前循环,也可以指定终止某一个循环,需给该循环起名
1
2
3
4
5
6
7
8
9
10
11
12public class BreakTest{
public static void main(String [] args){
outerFor:for(int i=1; i<10; i++){
innerFor:for(int j=10; j>0; j--){
System.out.println(j);
if(5 == j){
break outerFor;
}
}
}
}
}
continue 语句
- continue是java中的一个关键字
continue;
是一个完整的语句- continue语句默认继续当前循环,也可以指定继续某一个循环,需给该循环起名
键盘输入
1 | java.util.Scanner s = new java.util.Scanner(System.in); |
java 方法
方法的定义
1 | [修饰符列表] 返回值类型 方法名(形参列表){ |
修饰符列表:
- 可选项,不是必须的
- 方法中有
static
关键字,调用方式:ClassName.methodName(实参列表)返回值类型:
- 可以是java的任意一种数据类型
- 返回值类型是
void
,方法没有返回值。- 返回值类型不是
void
,必须有返回值,且返回值的类型与声明的返回值类型保持一致。方法名:
- 合法的标识符
- 命名应见名知意
- 方法名尽量使用动词
- 方法名使用小驼峰命名
说明
- 方法定义在类体当中,类体中可以定义多个方法
- 方法中不能在定义方法
方法执行过程中内存的分配
- 方法只定义,不调用,不会执行。JVM也不会给该方法分配运行所需的内存空间。只有再调用这个方法时,才会动态的给所调用的方法分配所需的内存空间。
- JVM在内存划分上有三个主要的内存空间:
- 方法区内存
- 堆内存
- 栈内存
- 数据结构
- 数据结构反应的是数据的存储形态
- 常见的数据结构
- 数组
- 队列
- 栈
- 链表
- 二叉树
- 哈希表 / 散列表
- 关于栈数据结构
- 栈 - stack,是一种数据结构
- 栈帧永远指向栈顶元素
- 栈顶元素出于活跃状态,其它元素处于静止状态
- 栈术语
- 压栈 / 入栈(push)
- 弹栈 / 出栈(pop)
- 栈数据结构存储数据的特点
- 先进后出 / 后进先出
- 方法代码片段在哪里?
- 方法代码片段属于class字节码文件的一部分
- 字节码文件在JVM加载后存储于方法区内内存中
- 方法区内存中最先有数据,存放代码片段
- 方法调用后,会在栈中给该方法分配内存空间(压栈动作)
- 方法结束后,会释放栈中所分配的内存空间(弹栈动作)
- 局部变量在栈中分配内存
示例
1 | public class MethodTest{ |
方法重载
说明
方法重载又被称为overload
功能相同,可以使用方法重载,让方法名形同
1
2
3
4
5
6
7
8
9
10
11
12public class OverloadTest{
public static void main(String [] args){
//方法参数列表不同
public static void method1();
public static void method1(int a);
//方法参数类型不同
public static void method2(double a);
public static void method2(int a);
public static void method2(long a);
}
}方法重载和方法名+参数列表有关
方法重载和返回值类型无关
方法重载和修饰符列表无关
示例
1 | public class MethodTest{ |
java面向对象
三大特质
- 封装
- 继承
- 多态
三个阶段
- 面向对象的分析:OOA (Object-Oriented Analysis)
- 面向对象的设计:OOD (Object-Oriented Design)
- 面向对象的编程:OOP (Object - Oriented Programming)
类和对象的概念
什么是类
- 类在现实世界中是不存在的,是人为抽象的一个概念
- 类代表现实世界中具有相同属性和行为的一类事物
什么是对象
- 对象是现实世界中真实存在的个体
类与对象的关系
- 类 –> 实例化为 –> 对象
- 对象 –> 抽象为 –> 类
- 对象又称为实例
对象的创建和使用
1 | // Husband.java |
JVM的内存管理
- JVM主要包括三块内存:方法去内存、栈内存和堆内存
- 堆内存和方法去内存各有一个,栈内存一个线程一个
- 方法及类的代码片段在加载时会存储于方法去内存中
- 方法调用是所需的内存在栈内存中分配,即压栈;方法调用结束后,栈中分配的内存将释放,即弹栈
- 在程序执行过程中使用
new
关键字创建java对象时,所创建的实例将会存储于堆内存当中 - 变量分类
- 成员变量(方法体外声明的变量)
- 实例变量(没有static修饰符)
- 静态变量(有static修饰符)
- 静态变量存储于方法区内存当中
- 局部变量(方法体中声明的变量)
- 成员变量(方法体外声明的变量)
- 三块内存当中频繁变化的是栈内存,最先有数据的是方法去内存,垃圾回收主要针对堆内存
- 垃圾回收器(自动垃圾回收、gc机制)
- 当内存中java对象没有被引用或无法使用时将是为垃圾,会自动回收
类的封装
类的构造方法
构造方法又称为构造函数或构造器
构造方法的语法
1
2
3[类型修饰符] 构造方法名(形参列表){
构造方法体;
}普通方法的语法
1
2
3[类型修饰符] 返回值类型 方法名(形参列表){
方法体;
}构造方法无返回值类型,若加上,则为普通方法
对于构造方法来说,构造方法的方法名必须和类名保持一致
构造方法的作用
- 通过调用构造方法可以创建对象
- 初始化实例变量
构造方法调用
1
constructorName var = new constructorName(para);
当类中没有构造方法时,系统会提供一个默认的无参数构造方法,称为缺省构造方法
当一个类中构造方法被定义后,就不会调用默认的缺省构造方法
构造方法可以重载
类的继承
作用
- 代码复用
- 方法覆盖
- 多态机制
语法
1 | [修饰符列表] class 类名 extends{ |
关于继承的一些术语
B类继承于A类
- A类称为:父类、基类、超类、superclass
- B类称为:子类、派生类、subclass
java类只支持单继承,不支持多继承
子类继承于父类的数据
- 私有地不支持继承
- 构造方法不支持继承
- 其他数据都可以继承
java类可以间接继承其他类
1
2
3A extends B{}
B extends C{}
c extends D{}java 类默认继承自
java.lang.Object
类
java方法的覆盖(重写)
- 私有方法不能覆盖
- 构造方法不能覆盖
- 覆盖只针对方法,不涉及属性
类的多态
涉及的概念
- 向上转型(upcasting)
- 子类型 –> 父类型
- 自动类型转换
- 向下转型(downcasting)
- 父类型 –> 子类型
- 强制类型转换(需加强之类型转换符)
- java允许父类型引用子类型对象
- 转型之间必须存在继承关系
关键字
this关键字
- this是一个引用
- 构造方法使用
this(para)
可以调用其它的构造方法,且只能出现在第一行
static关键字
带有static关键字的变量和方法为静态变量和类方法,通过类名调用或实例调用
不带有static关键字的变量和方法为实例变量和实例方法,通过实例调用
使用static定义静态代码块
语法
1
2
3static{
java语句;
}静态代码块在类加载时执行,且只执行一次。
静态代码块在类中可以编写多个
通常在静态代码块中完成数据的准备工作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public class Chinese {
String id;
String name;
String city;
static String country = "China";
static {
System.out.println("开始调用Chinese类。。。");
}
public Chinese() {}
public Chinese(String id, String name, String city) {
this.id = id;
this.name = name;
this.city = city;
}
}
final关键字
final表示最终的,不可变的
final修饰的类无法继承
final修饰的方法无法覆盖
final修饰的变量赋值后不可更改
final修饰的成员变量中的实例变量需要给其赋初始值,不能用默认值
1
2
3
4
5
6
7
8public class Test{
final String name = "Jack"; // 需要赋初始值,否则编译出错
final int age;
public Test(){
this.age = 20;
}
}final修饰的引用,一旦指向某个对象后,不能在指向其它对象
final和static一般连用,表示一个常量
1
2
3public class Test{
static final double PI = 3.141592654;
}
使用技巧
中文转译为unicode码
1 | {JAVA_HOME}/bin/native2ascii.exe |
异常处理
使用cmd命令出现“HelloWorld.java:3: 错误: 编码GBK的不可映射字符”解决方案
方法一:
1 | javac -encoding utf-8 HelloWorld.java |
方法二:
更改文件编码,如以GB2312编码方式保存文件。
1 | javac HelloWorld.java |