基础语法
IDEA快捷操作
Ctrl + D : 复制当前行到下一行
psvm : public static void main
sout : System.out.println();
for循环: fori Enter
Alt + Insert :
- 插入构造器
- 插入get、set方法
- @override 重写方法
Ctrl + H :继承树
Ctrl + Alt + T:自动生成异常等
Alt + Enter:提示如何处理异常
数据类型
基本数据类型
-
整型 默认值 0
int 4字节
byte 1字节
short 2字节
long 8字节,定义时要在后面加L,大小写均可,但是为了便于阅读用L
-
浮点型 默认值0.0
double 8字节,浮点数默认类型,如果要使用float类型要在后面加F
float 4字节,定义时要在后面加F
-
字符型
char 2字节
注:String是一个类,不是基本数据类型,也不是关键字
-
布尔类型 默认值为false
boolean 1位
引用数据类型
- 类
- 接口
- 数组
默认值为null
数据类型拓展
-
进制表示
二进制:0b110 = 6
八进制:0110 = 72
十六进制:0x110 = 272
浮点数会有舍入误差,最好完全避免使用浮点数直接比较!
-
字符的本质也是数字
ASCII编码:‘A’~‘Z’ 65~90 ‘a’~‘z’ 97~122
Unicode编码:2字节 0~65535
-
强制类型转换
高>>低 可以强转 (类型)变量名
低>>高 自动转换
byte short int long float double
布尔值不可以类型转换
可能会有溢出或者精度的问题
不能把对象类型转换成不相干的类型
char c = 'A'
System.out.println((int)c); //强制转换 把int括起来
-
转义字符
/t 制表符 /n 换行
常量与变量
常量
常量(Constant) 初始化(initialize)之后不会再改变
final Max = 65535; //final 常量名 = 值 ; 常量名一般大写开头
变量
变量的作用域
- 局部变量: 作用在方法里,必须声明和初始化值
- 实例变量:方法外面,类的里面,从属于对象,要先创建对象才可以使用,可以不进行初始化
- 类变量:加一个static关键字,会从属于类,跟实例变量一样,写在方法外面,类的里面,可以直接调用,不需要创建对象
变量命名规范
1.见名知意
2.类成员变量:首字母小写与驼峰原则:mouthSalary,除第一个字母,其余用大写开头
3.局部变量:首字母小写与驼峰原则
4.常量:全部大写,可加下划线 MAX_VALUE
5.类名:首字母大写与驼峰原则:Man,GoodMan
6.方法名:首字母小写与驼峰原则,run(),runRun()
操作符
关系运算符
大于 > 小于 < 等于 = 运算返回的是Boolean类型 true/ false
- a++与++a
int a = 3;
int a1 = 3;
int b = a++; //先把a赋值给b,然后a自增 执行完这行代码后,b=3,a=4
int b1 = ++a1; //a1先自增,然后才赋值给b 执行完这行代码后,b1=4,a1=4
逻辑运算符
与(AND)&& 或(OR)|| 非(NOT)!
短路运算
boolean a = true;
boolean b = false;
System.out.println("a&&b:"+(b&&a)); //b为假,后面的不会执行,直接输出假
System.out.println("a||b:"+(a||b)); //a为真,后面的不会执行,直接输出真
字符串连接
//字符串连接符 + , 有一侧为String 就会转成字符串
int c = 10;
int d = 20;
System.out.println(""+c+d); //输出结果为1020
System.out.println(c+d+"123");//字符串在后面,前面的还会运算,输出结果为30123
三元运算符
x ? y : z
如果x部分为true,则输出 y 部分,否则输出z部分
位运算
- &:按位与
- |:按位或
- ^:异或运算,相同为0,不同为1
- ~:非,按位取反
/*
A = 0011 1100
B = 0000 1101
A&B 0000 1100 按位与
A|B 0011 1101 按位或
A^B 0011 0001 异或 相同为0 不同为1
~B 1111 0010 非
2*8 = 16 2*2*2*2
<<左移 相当于乘2 >>右移相当于除以2
效率很高!
0000 0010 2
0000 0100 4
0000 1000 8
0001 0000 16
*/
程序控制流程
- 顺序 选择 循环
switch控制流程
char grade = 'A';
switch (grade){ //switch有穿透现象,如果不写break,自匹配成功之后的所有分支都会输出
case 'A':
System.out.println("Good!");
case 'B':
System.out.println("Normal!"); //normal也会输出
break;
case 'C':
System.out.println("Poor!");
}
jdk1.7后新特性:switch表达式可以为String
原理:字符的本质还是数字
反编译
Java源代码>>.class文件(字节码文件)>>Java程序
-------------------------------------------------------------------->编译
<------------------------------------------------------------------反编译
do-while与while
/*do{
}while( ) 至少执行一次
*/
/*while( ){
}
*/
Scanner类
- 凡是属于IO流的类如果不关闭会占用系统资源,要习惯性用完关闭
Scanner类:获取用户的输入
- next()、nextLine():获取输入的数据
- next():以空格作为分隔符,不能得到带有空格的字符串
- nextLine():可以获得空格,以 Enter键结束
Scanner scanner = new Scanner(Systen.in); //创建扫描器对象
String str = scanner.nextLine(); //等待用户输入
System.out.println(str); //输入输入的数据
scanner.close(); //关闭扫描器对象
- 判断是否还有输入的数据
- hasNext():
- hasNextLine():
//创建一个扫描器对象,用于接受键盘数据
Scanner scanner = new Scanner(System.in);
System.out.println("使用next方式接收:");
//判断用户有没有输入字符串
if(scanner.hasNext()){
String str = scanner.next(); //程序会等待输入后再继续运行
System.out.println("输出内容为:"+str);
scanner.close();//凡是属于IO流的类如果不关闭会占用资源,养成好习惯用完关掉
}
Scanner类常用方法
scanner.hasNext()、scanner.hasNextLine()、scanner.hasNextInt() 这些方法都是返回值类型为Boolean
scanner.next()、scanner.nextLine 获取字符串类型
scanner.nextInt()、scanner.nextDouble 获取整型、浮点型
Java方法
加一个static可以直接调用,不需要创建对象
/*
修饰符 返回值类型 方法名(形参列表){
方法体
return 返回值; //return是方法执行的最后一个语句,return下面的语句不会执行
}
*/
递归
/*递归
递归头:边界条件,即什么时候结束递归
递归体:调用自身
*/
public static void main(String[] args) {
System.out.println(f(5));
}
static public int f(int n){
if(n==1){
return 1; //边界条件
}
else {
return n*f(n-1); //调用自身
}
}
重载
方法名相同,但是参数列表不同,形参类型不同/形参个数不同
println(),可以输入多种数据类型,用的就是方法的重载
判断两个方法是否相同:方法名是否相同,参数列表是否相同
数组Array
-
使用注意事项
1.数组存放相同数据类型(任意数据类型)
2.数组也是对象 数组元素相当于对象的成员变量
3.数组长度是确定的,不可变,注意不要越界
int[] numbs ; //数组声明,但是没有在堆中分配空间
numbs = new int[10] ; //创建数组,在堆分配内存空间
int numbs1 = new int [10] ; //声明+创建
初始化
//三种初始化方法
//静态初始化
int[] a = {1,2,3,4,5};
//动态初始化 包含默认初始化
int[] b = new int[5];
//默认初始化
//数组是引用类型,它的元素相当于实例变量,因此一旦分配空间,每个元素按照实例变量同样的方式被隐式初始化
增强for循环
int[] numbs= {10,20,30,40,50};
for(int x :numbs){
System.out.println(x);
}
栈与堆
栈 stack
- 存放基本数据类型 ,会存值
- 存放引用对象在堆中的地址
- Java中main()方法会在栈底,main()方法弹出后程序也就结束了
堆 heap
- 存放new的对象和数组
- 可以被所有线程共享,不会存放别的对象引用
方法区(也在堆中)
- 可以被所有线程共享
- 包括所有的class与static变量
面向对象编程(oop:object-oriented programming)
- 面向对象编程的本质:以类的方式组织代码,以对象的形式封装数据
- 三大特性:封装、继承、多态
- 从认知论的角度说,是先有对象后有类。
- 从代码运行角度说,是先有类,后有对象。类是对象的模板。
- 静态方法static是和类一起加载(在静态方法区里),非静态方法是要类实例化(创建了对象)之后才存在
- 值传递和引用传递:Java都是值传递
类与对象
-
类是一个模板,对象是类的实例
-
方法:定义、调用
-
对应的引用
- 引用类型: 除了8种基本类型
- 对象是通过引用来操作的:栈----->堆(地址)
- 引用类型: 除了8种基本类型
-
属性:字段(field) 成员变量
- 默认会初始化:
- 数字:0 、 0.0
- char:u0000
- Boolean:false
- 引用类型:null
- 定义公式: 修饰符 属性类型 属性名 = 属性值 ;
- 默认会初始化:
-
对象的创建和使用
- 必须使用***new***关键字创建对象,调用构造器 Person zhangsan = new Person();
- 对象的属性 zhangsan.name
- 对象的方法 zhangsan.run()
-
类
- 静态的属性 ---- 属性
- 动态的行为 ---- 方法
new关键字
- 使用new关键字来创建对象
- 使用new关键字创建时,除了分配内存空间外,还会给创建好的对象进行默认的初始化,以及对类中构造器的调用
public class Student {
//属性:字段
String name; //默认值为null
int age; //0
//方法
public void stude(){
System.out.println(this.name+"在学习"); //this关键字
}
//类型 类型名 = 类型值
Student zhangsan = new Student();
zhangsan.name = "zhangsan";
zhangsan.age = 25;
构造器
-
类中的构造器也被称为构造方法,是在进行创建对象的时候必须要调用的,
-
构造器特点:
-
1.必须和类名相同
-
2.必须没有返回值类型,也不能写void
-
-
构造器作用:
-
1.new 关键字本质是在调用构造方法
-
2.初始化对象值
-
-
注意点:
- 1.如果定义了有参构造,必须要显式定义无参构造
- 即:不写的话会默认存在一个无参构造,写了有参构造后就这个无参构造就没了
- 2.this. = 通常前面表示当前类,后面表示传进来的参数
public class Person { String name; int age; //显式定义构造器 //无参构造 public Person(){ } //有参构造:一旦定义了有参构造,无参就必须显式定义 //构造方法的重载 public Person(String name, int age) { this.name = name; //name为形参,this.name为对象属性的name this.age = age; } /* Person person = new Person(); Person zhangsan = new Person("zhangsan",12); */
- 1.如果定义了有参构造,必须要显式定义无参构造
封装(数据的隐藏)
- 属性私有,get/set
- 高内聚,低耦合
- 通常应该禁止直接访问一个对象中数据的实际表示,而应该通过操作接口来访问,这叫做信息隐藏
继承
-
继承的本质是对一批类的抽象,从而实现对现实世界更好地建模
-
关键字 extends:“扩展”。子类是父类的扩展
-
子类与父类,在意义上具有“ is a” 的关系
-
子类继承父类,就会有父类的全部的方法(public)
-
私有的对象无法被继承
-
四个权限:public protected default private
-
在Java中,所有的类都直接或间接继承Object类
-
Java中只有单继承,没有多继承
super关键字
- super调用父类的构造方法,必须在构造方法的第一个
- super 必须只能出现在子类方法或者构造方法中
- super 和 this 不能同时调用构造方法
VS this
- 代表的对象不同:
- this:本身调用这个对象
- super 代表父类对象的引用
- 前提
- this没有继承也可以使用
- super只能在继承条件下才可以使用
- 构造方法
- this():本类的构造
- super():父类的构造
方法重写
- 前提:需要用继承关系,子类重写父类的方法!
- 1.方法名必须相同
- 2.参数列表必须相同
- 3.修饰符:范围扩大: public>protected>default>private
- 4.抛出的异常:范围:可以被缩小,但不能被扩大; ClassNotFoundException —>Exception(大)
- 重写,子类的方法要和父类方法一致,方法体不同!
- 为什么需要重写?
- 父类的功能,子类不一定需要,或者不一定满足
方法重写:子类方法与父类方法一模一样 子类继承父类才能重写,子类重写父类的方法
方法重载:参数名不一样,相当于是本类的
静态方法:方法的调用只和左边,定义的数据类型有关,与重写无关
多态
动态编译:类型:可扩展性
方法的多态,属性没有多态
抽象(编程思想):封装、继承、多态 抽象类 、接口,
父类型的引用指向子类型的对象
- 子类转换为父类,向上转型,自动,丢失子类中特有的方法
- 父类转换为子类,向下转型,强转,丢失父类被子类重写过的方法
- 方便方法的调用,减少重复的代码
同一个方法可以根据发送对象的不同而采取多种不同的行为方式
一个对象的实际类型是确定的,但是可以指向对象的引用的类型可以非常多(父类,有关系的类)
- 注意事项
- 方法的多态,属性没有多态
- 父类和子类,有联系 类型转换异常ClassCastException
- 存在条件:继承关系,方法需要重写,父类的引用是指向的子类对象 Father f1 = new Son();
- 不能被重写的方法: 自然没有多态
- 1.static 方法,属于类,不属于实例
- 2.final 常量;
- 3.private方法;
- 不能被重写的方法: 自然没有多态
instanceof关键字
X instanceof Y :X所指向的实际类型,是不是Y类型的子类型,如果是则返回ture,否则返回false
引用类型转换
- 基本类型转换:高---->低 强转 丢失精度
- 引用类型转换:父----->子 强转
Person obj = new Student();
//将student对象转成Student类型,就可以使用Student类型方法了
Student student = (Student2)obj; //obj类型强转,高转低
student.go(); //go()方法为Student子类里的方法
//((Student2)obj).go();
//子类转父类 可能丢失自己的一些方法
Person2 person2 = obj;
//obj.go;不可以
static关键字
- 被static修饰的属性,可以通过类名来直接访问。而非静态属性只能通过创建对象来访问。
- 被static修饰的方法,可以通过类名.方法名访问,而非静态方法需要创建对象来访问
- 静态可以访问静态,非静态可以访问非静态,但是不能相互访问,因为创建时间不同
匿名代码块 静态代码块
public class Person {
//2:与创建对象同时产生,可以用来赋初始值
{
//代码块(匿名代码块)
System.out.println("匿名代码块");
}
//1.只执行一次
static{
//静态代码块
System.out.println("静态代码块");
}
//3.
public Person(){
System.out.println("构造方法");
}
public static void main(String[] args) {
Person0 person0 = new Person();
System.out.println("==========================");
Person0 person1 = new Person();
}
}
/*
静态代码块
匿名代码块
构造方法
==========================
匿名代码块
构造方法
*/
静态导入包
import static java.lang.Math.random;
import static java.lang.Math.PI;
public class Test{
System.out.println(random());
System.out.println(PI);
}
抽象类
abstract关键字,声明抽象类/抽象方法,extens去继承实现
- 抽象类是一种约束,抽象方法只有方法名,没有方法体
- 抽象类中的抽象方法,必须由继承它的子类实现,除非子类仍然是抽象类*
- 不能new抽象类,只能靠子类来实现
- 抽象类可以写普通方法,但是抽象方法必须在抽象类中
接口(interface)
interface定义接口,implements实现,可以进行多继承
普通类:只有具体实现
抽象类:具体实现和规范(抽象方法)都有
接口:只有规范,自己无法写方法 约束和实现分离:面向接口编程
接口的本质是契约
- 接口就是规范,定义的是一组规则
- OO的精髓,就是对于对象的抽象,最能体现这一点的,就是接口
- 设计模式所研究的,就是如何合理地去抽象
作用:
- 约束
- 定义一些方法,让不同的人实现
- 方法都是public abstract
- 常量都是public static final
- 接口不能被实例化,接口中没有构造方法
- 可以实现多个 implements
- 必须重写接口中的方法
public interface UserService {
//常量 public static final
int age = 99;
//接口中所有的定义的方法其实都是抽象的 public abstract
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
public interface TimeService {
void timer();
}
//接口实现,使用implements关键字,可以实现多个接口
public class UserServiceImpl implements UserService,TimeService{
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
//利用接口实现多继承
@Override
public void timer() {
}
}
内部类
- 内部类就是在一个类中,又定义了一个类
- 一个Java类中可以有多个class类,但是只能有一个public class
public class Outer {
private int id = 10;
public void out(){
System.out.println("这是外部类的方法");
}
//局部内部类
public class Inner {
public void in(){
System.out.println("这是内部类的方法");
}
//内部类可以获得外部类的私有属性
public void getId(){
System.out.println(id);
}
}
}
//main()方法
Outer outer = new Outer();
//通过这个外部类来实例化内部类
Outer.Inner inner = outer.new Inner();
inner.in();
inner.getId();
异常机制Exception
- 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
- 运行时异常:运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
- 错误ERROR:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
在Java中,把异常当作对象处理,定义了一个java.lang.Throwable作为所有异常的超类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gdGxx8ep-1631541857856)(E:\Note\Java异常处理.PNG)]
可以分成运行时异常与非运行时异常
- Error与Exception的区别:Error通常是灾难性的致命错误,是程序无法控制和处理的。当出现这些异常时,Java虚拟机(JVM)会终止线程。Exception通常情况下是可以被程序处理的,并且在程序中应该 尽可能的去处理这些异常。
异常处理五个关键字
- try:监控区域
- catch:捕获异常
- finally:无论是否有异常都要执行
- throw:主动抛出异常
- throws:方法中处理不了异常,方法上抛出异常
public static void main(String[] args) {
int a = 1;
int b = 0;
try{//try监控区域 一般try与catch连用
if (b==0){
throw new ArithmeticException();//主动抛出异常
}
System.out.println(a/b);
}catch(Error e) { //catch(想要捕获的异常类型,最高为Throwable)
System.out.println("Error");
}catch(Exception e){
System.out.println("Exception");
}
catch(Throwable e){//范围要从小到达,否则下面的小范围异常类型会被上面的大类型覆盖
System.out.println("Throwable");
}
finally{//finally一般用来处理善后工作 无论是否出异常都会执行 可以不要finally 假设IO,资源,关闭!
System.out.println("finally");
}
}
实践经验
- 处理运行时异常时,采用逻辑去合理规避同时辅助try-catch处理
- 在多重catch后面,可以加一个catch(Exception)来处理可能会被遗漏的异常
- 对于不确定的代码,也可以加上try-catch,处理潜在异常
- 尽量去处理异常,切忌只是简单地调用printStackTrace()去打印输出
- 具体如何处理异常,要根据不同的业务需求和异常类型去决定
- 尽量添加finally语句块去释放占用的资源 IO流用到的比较多
自定义异常(较少用到)
用户自定义异常类,只需要继承Exception类即可。
创建自定义异常类步骤:
- 创建自定义异常类
- 在方法中通过throw关键字抛出异常对象
- 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出方法给调用者的异常,继续进行下一步操作。
- 在出现异常方法的调用者中捕获并处理异常。