# Java基本语法笔记
Java是一种可以编写跨平台的、面向对象的程序设计语言
数据类型
● 整型
byte 1字节 -168~167
short 2字节 -32768~32767
int 4字节 -2147483648~2147483637
long 8字节
● 浮点类型
float 4字节 有效位数6~7位
double 8字节 有效位数15位(双精度)
(16进制:0.125表示为0x1.0p-3 位数采用16进制,指数采用10进制,指数的基数采用2进制)
● 字符类型
char 2字节 用UTF-16编码描述一个代码单元
● 布尔类型
boolean 1字节 true/false 在Java中整型值与布尔值之间不能相互转换
(在Java中,所有的数值类型所占据的字节数量与平台无关)
● 枚举类型
枚举类型包含有限个命名的值
enum Size {SMALL, MEDIUM, LARGE, EXTRA_LARGE}
● 常量
使用final关键字,习惯上使用大写 使用 static final表示类常量
(类常量如果定义位于main方法外部,可以在同一个类的其他方法中使用,如果声明为public类型,也可以在其他类的方法中使用)
● 变量
遵循标识符命名规则
尽量使用有意义的单词
大小写敏感,首字母一般小写
(标识符包括 : A~Z 、a-z 、_ 、$ )
● 运算符
+、-、x、/、%、+=、-=、*=、/=、%=、++、– 、算术运算符
==、!=、>=、<=、>、< 、关系运算符
& 、| 、!、^、&& 、|| 、 逻辑运算符
<<、>>、>>> 、 移位运算符(右移、左移、无符号右移,无<<<运算符)
k = x ? y :z 、三元运算符
instanceof (见备注5)
% 格式说明符(见备注6)
(1. 取模运算不适用浮点类型,结果不准确
2. 对于精度高的运算,可使用BigDecimal类型
3. 逻辑运算先求所有条件值再做判断;短路运算求第一个条件值后进行判断,为真进行后续求值判断,为假直接返回得出结果
4 . >>>运算符用0填充最高位,>>运算符用符号位填充最高位,负数的移位运算需要先转化为补码的形式再进行移位
5. 左面的操作元是一个对象,右面是一个类或接口。当左面的对象是右面的类(或右边类的子孙类)创建的对象、或者是右边接口的实现类(或实现类的子孙类)的对象时,是true,否则是false
6. 每一个以%字符开始的格式说明符都有相应的参数替换。格式说明符尾部的转换符将指示被转化的数字类型)
● 运算符优先级
数据类型转换
● 自动类型转换
目的类型比原来的类型要大
两种类型是相互兼容的
● 强制类型转换:
浮点型转到整形,截掉小数位,保留整数位 丢掉小数部分,3.5555->3
长整形转到短整形, 丢失高位,int - 4个字节 32位,byte - 1个字节 8位
字符串
● 字符串连接:
使用 + 来连接两个字符串
● 转义字符:
编译器将转义字符当作一个字符
\n 换行符
\t 制表符
\r 回车符,光标回到本行开始处
● 字符串截取子串:
substring(a,b); //参数a表示开始截取的位置,b表示结束截取的位置,长度为b-a
● 测试字符串是否相等:
Object equals 两个对象的内存地址相等
String equals 两个字符串的内容相等
1.维护在常量池里面
String a = "hello";
String b = "hello";
2.只要是new出来的都是新对象,保存在堆内存中
String c = new String("hello");
● 字符串比较:
equal(); 比较两个变量是否相等
compareTo(); 比较字符串对应字符的大小(ASCII码顺序),返回int类型
compareTo()是值比较,equals()是对象比较
(一定不要使用 == 运算符检测两个字符串是否相等!这个运算符只能确定两个字符串是否放置在同一位置上)
● str.intern();//返回字符串规范化的表现形式
调用str.intern()方法的时候,会将共享池中的字符串与外部的字符串(str)进行比较,如果共享池中有与之相等的字符串,则不会将外部的字符串放到共享池中的,返回的只是共享池中的字符串,如果不同则将外部字符串放入共享池中,并返回其字符串的句柄(引用),好处是节约空间
● Stringbuilder
字符串构建字符串建议使用StringBuilder类,避免即耗时又浪费空间的问题
String、StringBuffer、StringBuilder三者区别:点击查看
流程控制
● 流程控制之选择
- if 条件语句
if(条件){ 内容 }else{ 内容 }
(条件可以为boolean类型的值、变量、表达式)
- switch语句
switch(表达式){ }
1. 表达式类型:byte、short、char、int、enum(java5引入)、string(java7之后才支持)
2. value的值必须和表达式类型一致,或者兼容,不能出现重复的value值
● 流程控制之循环
- while循环
while(条件){ 内容 }
do{ 内容 }while(条件) //循环至少执行一次
条件可以是boolean类型的值、变量、表达式、方法
- for循环
for(初始化①;条件②;迭代运算③){ ④ }
1.条件必须是boolean表达式
2.执行过程:①->②–>真④—>③–>②…;①->②–>假–>结束
3.可以在各自独立的不同for循环中定义同名的变量
● 流程控制之跳转
break 强制当前循环终止(当前循环所在的子循环)
continue 强制停止本次循环
return 从当前方法中退出
大数值
● BigInteger、BigDecimal
使用静态的valueOf方法可将普通的数值转换为大数值
无法使用常用的算数符处理大数据,需要使用以下方式:
BigInteger add(BigInteger other) //和
BigInteger subtract(BigInteger other) //差
BigInteger multiply(BigInteger other) //积
BigInteger divide(BigInteger other) //商
BigInteger mod(BigInteger other) //余数
int compareTo(BigInteger other) //比较大小
static BigInteger valueOf(long x) //返回x的大整数
● 数组
- 申明数组:
ArrayType arrayName[] ; //方式一
ArrayType[] arrayName; //方式二
- 初始化数组:
ArrayType[] arrayName = new ArrayType[length]
ArrayType[] arrayName = {};
new ArrayType[]{};
- 数组复制:
array1 = array2;
复制之后,两个引用指向同一个数组 ,无论哪个引用改变了数组的值,对于另一个引用来说,元素的值也随着改变。
- 多维数组:
java中只存在一维数组,所以多维数组指数组中的数组
二维数组:int[][] n = new int[5][5]
初始化有两种方式:双重循环赋值初始化,声明时直接初始化
- for each循环
格式:for(variable : collection) statement
意义:依次处理数组中的每个元素而不必为指定下标值而分心,相对于for循环更加的简洁
- 其他常用方法:
static Sring toString(type[] a) //返回包含a中数据元素的字符串
static type copyOf(type[] a, int length)
static type copyOf(type[] a, int start, int end) //返回与a类型相同的一个数组
static void sort(type[] a) //使用优化的快速排序算法
static int binarySearch(type[] a,type v)
static int binarySearch(type[] a,int start, int end, type v) //采用二分法查找V,成功找到返回相应的下标值
static void fill(type[] a,type v) //将数组的所有元素设置为v
static boolean equals(type[] a,type[] b) //数组比较(大小,下标相同的元素也相同)
● 数组与集合
- 区别:
数组长度固定,集合长度可变
数组只能通过下标访问元素,类型固定;而有的集合可以通过任意类型查找所映射的具体对象
- 分类:
类
概述:
类就是事物的集合和抽象。他所代表的是这类事物所共有的一些行为和属性
- 形式:
class 类名 {
类型 变量名;
类型 方法名(参数){
//方法体...
}
}
- 修饰符:可以修饰类、属性、方法
private 只有在本类中可以看见
protected 在同类或者包里面可见
public 对于所有类可见
默认 (无修饰符):在本类或者一个包里面可见
● 方法
- 方法 :
方法无返回值,必须写void,不能省略
方法有返回值,值返回类型与方法体内返回值类型相同
- main方法:
main方法是程序的入口
public static void main(string[]args){
//方法体...
}
- this(隐式参数)
在每个方法中,关键字this表示隐式参数
● 构造方法
- 构造方法:(作用)初始化参数
数字:默认为0,
boolean:默认为false,
对象变量:默认为null
- 设计自己的构造方法:
1.方法名与类名相同
2.没有返回值
3.如果自己手动设置了有参的构造方法,那么编辑器不会提供默认的构造方法,如想用无参的构造方法,需自己手动实现
- 关于构造器有话说:
1.构造器与类同名
2.每个类可以有一个以上的构造器
3.构造器可以有0个、1个或多个参数
4.构造器没有返回值
5.构造器总是伴随着new操作符一起调用
(仅当类没有提供任何构造器的时候,系统才会提供一个默认的构造器;如果类中提供了一个构造器,但是没有提供一个无参的构造器,则在构造对象时如果没有提供参数就会被视为不合法)
● 方法的重载
1,在一个类中,可以有多个方法共享同一个名称,只要他们的参数不同即可,根据参数类型和个数决定调用哪个方法
(重载:具有相同的方法名称,不同的参数列表)
(不同的参数列表:参数个数、参数类型、参数次序)2,方法的名字和参数列表称为方法的签名,如果子类中定义了一个与超类签名相同的方法,那么子类的这个方法就覆盖了超类的方法,在覆盖方法时,需要保证返回类型的兼容性,允许子类将方法返回的类型定义为原返回类型的子类型
对象
1,对象的创建:
对象是类的实例化引用
2,构造函数的重载:
调用父类的构造器,即Object
3,对象类型的参数传递:
Java中只有值传递;基本类型直接传值,引用类型传递的是引用,引用就是值
基本数据类型作为参数,直接操作
引用类型作为参数,操作的是引用指向的堆内存中的对象
● static 关键字
1,静态变量:
静态变量属于类,与对象无关
非静态变量是属于某个对象,每个对象都有该数据的副本,而静态变量只有一个
访问静态变量是通过 ”类名.变量名“来访问的
2,静态方法:
用static修饰的方法
访问静态方法是通过“ 类名.方法名“形式
静态方法不能访问非静态变量
非静态方法能访问静态变量
静态属性或方法是在类加载时产生的
非静态的属性或方法是在new的时候产生的
3,静态变量:
public static int X = 123;
● final 关键字
1,final修饰变量:
恒定不变的属性使用final修饰
变量名建议全部使用大写
final修饰的变量无法改变
2,final修饰方法:
3,final修饰类:
该类不能做为任何类的父类,类中的方法会全部被自动定义为final类型
包
● 包的介绍:
命名包
未命名包(default package)–尽可能避免使用
封装
1,概述:
数据和对数据的操作绑定到一个类中的方法,保障程序数据不受外部代码影响
2,实现封装:
通过get()、set()方法实现封装
(不要编写返回引用可变对象的访问器方法 ,这不符合设计规则)
继承
1 , 继承概念:
父类,基类,超类
子类,派生类
1. extends 只能继承一个类,java不支持多重继承
2. 子类继承父类后可调用父类属性和方法,也可以重写属性和方法,final修饰的除外,子类可以增加新的属性和方法
2,实现继承:
创建子类对象的过程就是从底层的基类开始往上,一层一层的调用构造方法
super();
1. 在调用子类的构造器的时候,如果没有显示的写出super(),那么编译器会默认加上super()无参构造器;如果要调用父类的有参构造器,必须显示的进行调用
2. super() 调用必须放到方法的第一个语句中
3,继承关系:
java只支持单继承
多态
如何理解多态:
一个对象的多种状态
(dog可以看作是dog,也可以看作是animal)
一个超类的变量既可以引用一个超类对象,也可以引用任何一个子类的对象
抽象类
1,定义:
抽象类是为子类提供一个规范(规范、继承),一种模板作用
修饰符 abstract class 类名{
//类体...
}
抽象方法没有方法体:public abstract void set();
普通方法有方法体:public void
抽象类中至少有一个抽象方法,也可以有普通方法
存在抽象方法的类一定是抽象类
2,使用:
@Override 检测是否重写成功
一个类继承了抽象类,就必须重写抽象类中的所有抽象方法
如果有一个类没有重写抽象类的抽象方法,那么这个类也要定义为抽象类
接口
1,接口论述:
abstract class 抽象类的修饰符
interface 接口的修饰符
extends 只能是一个
implements 可以是多个
接口只有抽象方法,比抽象类还要抽象
接口是抽象方法和常量的属性集合
接口中只能包含抽象方法和常量,不能有变量、初始化块、构造器
2,注意事项:
接口修饰符只有两种,默认的和public
接口内只有抽象方法和常量的属性集合
接口内的变量会被设置成共有的、静态的、最终的字段
int i =1; --变量自动默认转为常量--> public static final int i =1;
3,接口的实现:
class 类名 implements 接口1,接口2{
//方法体...
}
4,实现的规则:
为接口中所有的方法提供具体实现
必须遵守重写的规则
保持相同的返回类型
重写规则:
1.子类的重写方法不能抛出更大的异常
2.子类的重写方法不能有更小的访问范围
5,接口实现多继承:
多个接口之间使用逗号分隔
如果多个接口都有相同的方法和变量,那么相同的变量可以可以通过“ 接口名.变量名 ”的形式来访问,相同的方法将被其中的一个接口使用
6,接口的应用:
接口中变量修饰符: public static final
接口中方法修饰符: public abstract
7,接口与抽象类的区别:
1.接口是公开的,里面不能有私有的方法或者变量,而抽象类可以有私有的变量和方法
2. 实现接口一定要实现接口里定义的所有方法,而实现抽象类可以有选择的重写需要用到的方法,一般应用里,最顶级的是接口,然后是抽象类实现接口,最后才是具体类的实现
3.接口可以实现多继承,而一个类只能继承一个超类,但可以通过继承多个接口实现多继承,接口还有标识(里面没有任何方法)和数据共享(里面的变量全是常量)的作用
4. 接口只能包含抽象方法,抽象类可以包含已经实现的具体方法
5. 接口只能定义静态常量属性,抽象类既可以定义普通属性,也可以定义静态常量属性
6. 接口不包含构造方法,抽象类里可以包含构造方法
内部类
1,概述:
一个类被嵌套在另一个类中,那么这个类就是内部类,包含内部类的类就是外部类
2,构造内部类:(非静态内部类)
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.print();
3,匿名内部类:
public class Test02 {
public static void main(String[] args) {
OuterI outer = new OuterI(){
@Override
public void show() {
System.out.println("匿名内部类的show方法!");
}
};
outer.show();
}
//接口
public interface OuterI{
//接口方法
public void show();
}
}
4,局部内部类:
在类的局部位置进行定义的类叫做局部内部类
在局部内部类里面可以访问外部类的所有成员变量,局部内部类访问方法中的局部变量时,该局部变量必须声明为final类型
(jdk1.8版本可以访问非final类型的局部变量)
5,静态内部类:
在内部类前添加static修饰符
静态内部类中可以申明static成员变量,非静态内部类中不可以
静态内部类中不可以使用外部类的非静态成员变量
创建静态内部类的对象不需要其外部类的对象
Outer.Inner inner = new Outer.Inner();
6,引用外部类对象:
Inner : this.count
Outer : Outer.this.count
异常
1,概述:
程序运行过程中出现不正常的现象
2,关键字:
try : 把可能发生异常的代码包起来,当发生异常时抛出异常
catch :捕获异常并处理
finally :不管是否发生异常都会执行
throw :手动引发一个异常
throws :定义任何被调用方法的异常
3,异常原因:
用户输入错误 (大小,类型…)
代码的错误 (数组越界…)
环境的因素
4,异常作用:
异常的处理保证了程序的健壮性
5,异常分类:
Throwable接口 = Error + Exception(所有异常的父类)
Error :java运行时内部错误以及资源耗尽错误,很难恢复
RuntimeException:运行时异常
非RuntimeException:由环境异常导致
6,异常声明:
一个方法不处理它所产生的异常,而是调用层次向上传递,谁调用这个方法谁来处理
public void test () throws AirthmeticException{
System.out.println(1/0);
}
7,手动抛出异常:
throw exception;参数exception表示要抛出的异常对象,该对象是throwable类的子类,而且只能够是一个
try catch finally 是可以嵌套使用的
try 不能单独出现,后面必须跟着catch或者finally或者两者都有
8,创建自己的异常类:
继承Throwable
继承Exception
public class TestException {
public static void main(String[] args) {
try {
System.out.println(ageLevel(150));
} catch (IllegalAgeException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
public static String ageLevel(int age) throws IllegalAgeException {
if (10 <= age && age < 18) {
return "少年";
} else if (18 <= age && age < 24) {
return "青年";
} else if (24 <= age && age < 60) {
return "中年";
} else if (60 <= age && age < 120) {
return "老年";
} else {
throw new IllegalAgeException("非法的年龄!!!");
}
}
}
/**
* 定义自己的异常
* @author hzx
*/
@SuppressWarnings("serial")
class IllegalAgeException extends Exception {
public IllegalAgeException(String msg) {
super(msg);
}
}
线程与进程
1,概述:
线程:java语言内置多线程机制
进程:执行中的程序
2 , 关系:
线程可理解为轻量级的进程
线程本身不能单独运行,必须放在一个进程中运行
3,线程模型:
新建状态:线程被创建之后
就绪状态:新建状态的线程调用start()方法进入就绪状态 or 阻塞状态的线程解除阻塞之后进入就绪状态
运行状态:处于就绪状态的线程获得CPU资源(时间片)后就进入运行状态
阻塞状态:一个正在运行的线程因为一些原因让出CPU资源暂时中止进入的状态
终止状态:正常终止、强制终止:stop() 、destroy() 、异常中止:当线程产生异常时线程就会终止
4,流程图:
5,创建线程:
//方法一:继承Thread类来创建线程
修饰符 class 类名 extends Thread{
public void run(){
//代码
}
}
//方法二:实现Runnable接口
修饰符 class 类名 implements Runnable{
public void run(){
//代码
}
}
6,两种创建方式比较:
extends Thread //单继承
ChildThread childThread = new ChildThread();
childThread.start();
implements Runnable //多实现
ChildThread childThread = new ChildThread();
Thread mt = new Thread(childThread);
mt.start();
7,多线程应用:
(1)多线程并发执行:
Java对于线程启动后唯一能保证的是每个线程都被启动并且结束,但是对于哪个线程先执行或者是后执行是没有保证的
(2)线程优先级:1~10
thread.getPriority();
Java中优先级高的线程有更大可能性获得CPU资源,但不是优先级高的线程总是先执行,也不是优先级低的线程总是后执行
8,线程调度的三个方法:
休眠方法sleep(毫秒数) //sleep(毫秒数,纳秒数)
暂停方法yield() //调用之后释放资源,然后又去竞争(最好勿用)
挂起方法join() //调用之后会先去执行,类似于插队
9,线程同步问题:
由来:多个线程共享资源没有进行控制(打印机案例)
解决:
(1)同步方法:当线程进入同步方法的时候,会获得同步方法所属对象的锁,一旦获得对象锁,则其他线程不能再执行被锁对象的其他任何同步方法,只有在同步方法执行完毕之后释放了锁,其它线程才能执行
synchronized 方法声明{
}
(2)同步块:
synchronized(资源对象){
}
10,线程死锁问题:
A线程需要获得资源1才能继续执行,而资源1被线程B所占有;线程B需要获得资源2才能继续执行,而资源2被线程A所占有