什么是Java?
Java是一门面向对象的编程语言
编程语言:计算机可以识别并理解的语言
面向对象:对象即为具有某些特殊属性(成员、变量)和行为方式(方法)的实体
Java的优势
- 需求范围广,网站、微信小程序、手机app等都是基于Java语言编写的
- 学习成本低,Java为最简单的高级语言
Java的三大版本
- JavaSE Java基础班 重中之重
- JavaEE Java进阶版 做网站的必备技术
- JavaME Java进阶版 时代久远不做学习
Java的开发工具
eclipse
优点:免费、简单
缺点:功能少
idea
优点:功能多
缺点:收费、使用复杂
项目的目录规范与命名规范
目录规范:
- project 表示项目名,例如goods_manage_system(商品管理) demo2201(演示2201)
- JRE(Java的必备运行环境)和src(存放源代码的地方)
- package(包),方便分类管理若干个源代码文件,一般使用公司域名倒写
- 类,.java后缀的文件,java程序的源代码
命名规范:
项目名:纯小写,不包含中文。多个单词用下划线隔开即可
包名:公司域名倒写。例如com.yyzy.test
类名:大驼峰命名法。每个单词的首字母均大写。多个单词直接拼接,通过大写区分,例如:GoodsPrice 商品价格
常见基础代码
Java注释的分类
什么是注释?
方便后续程序猿阅读并理解,注释并不会被运行。
常见的三个注释类型:
- 单行注释:// 只进行本行注释 例如:
//作者比吴彦祖帅
- 多行注释:/* */ 进行多行注释 例如:
/*作者比吴彦祖帅
确实,见过本人确实如此*/
- 文档注释:/** */ 与多行注释类似,用途较少,不做演示
Java基本数据类型
数字类型:byte、short、int、long
字符类型:char
布尔类型:Boolean
浮点类型:float、double
如何声明一个变量
//声明的语法:数据类型 变量名 = 变量值;
//数据类型变量声明示例:
//整数
byte num1 = 10;
short num2 = 11;
int num3 = 12;
long num4 = 13;
//小数
//当需要float来存放小数时,需要在后面补上f
float num5 = 13.5f;
double num6 = 13.5;
//字符类型变量声明示例:
cahr name = '小明';
//布尔类型变量声明示例:
//只有Boolean才能存储布尔类型
boolean isPig = true;
//java中常见的运算符
//1.赋值运算符 = 将右边的值赋值给左边
int a = 123;
int b = a;
System.out.println(a);
System.out.println(b);
//算术运算符 + - * /
int a = 10;
int b = 11;
System.out.println(a+b);
//算术运算符 % 取余数
System.out.println(10%3);//1
//算术运算符 ++ --
//语法 a++ 和 a-- 表示先用(执行)在加或减
int a = 10;
a++;
System.out.println(a);//11
int a = 10;
System.out.println(a++);//10
//语法: --a ++a 先加减再用
int a = 10;
--a;
System.out.println(a);//9
int b = 10;
++b;
System.out.println(b);//11
//关系运算符:
//> >= < <= == != 他们的返回值都是boolean类型
int a = 10;
int b = 9;
System.out.println(a>b);
//逻辑运算符 && 短路与 || 短路或
// 语法如下: 表达式1 && 表达式2
//两个表达式都是true 才返回true
//如果一个为false 那么结果就是false
//运算从左到右。所以如果第一个式子为false 将不会执行第二个式子。
int a = 10;
int b = 9 ;
System.out.println(a>b && b<a);//true
System.out.println(a>b && b++<a);//true
// || 短路或
// 语法如下: 表达式1 || 表达式2
//两个表达式都是false 才返回false
//如果一个为true 那么结果就是true
//运算从左到右。所以如果第一个式子为true 将不会执行第二个式子。
//& 和 | :
//和上述用法完全一致,唯一区别:没有短路功能
//&和| 左右两边的式子都会执行
//例题:
int a = 10;
int b = 9;
System.out.println(a<b && a++>10 );//false
System.out.println(a);
int a = 10;
int b = 9;
System.out.println(a<b & a++>10 );//false
System.out.println(a);
//三元表达式:语法:表达式1?值1:值2
//表示:如果表达式1为true就是值1 反之就是值2
int age = 20;
System.out.println(age>18?"成年":"未成年");
判断语句
if语句
1.if
格式为:
if(条件判断语句){
执行语句;
}
2.if-else
格式为:
if(条件判断语句){
执行语句1;
}else{
执行语句2;
}
3.if-else if
格式为:
if(条件判断语句1){
执行语句1;
}else if(条件判断语句2){
执行语句2;
}
……
else if(条件判断语句n) {
执行语句n;
}else{
执行语句n+1;
}
switch语句
1.语法格式:
switch(条件判断语句){
case 常量1:
执行语句1;
break;
case 常量2:
执行语句2;
break;
……
default
执行语句n;
break;
}
循环语句
只要是循环语句或者来说只要是循环结构,一定会有四个要素:
- 初始化条件
- 循环条件( 表达式或者布尔类型)
- 循环体
- 迭代部分
for语句
for(变量;判断语句;迭代语句){
循环体;
}
运行过程:变量-判断语句-循环体-迭代语句-判断语句-循环体……判断语句(直到不满足条件)
while语句
变量;
while(判断语句){
循环体1;
迭代语句;
}
运行过程:变量-判断语句-循环体-迭代语句-判断语句-循环体……判断语句(直到不满足条件)
do-while语句
变量 ;
do{
循环体;
迭代语语句;
}while(判断语句)
运行过程:变量-判断语句-循环体-迭代语句-判断语句-循环体……判断语句(直到不满足条件)
- do- whlie语句会至少执行一次循环体
- 三循环可以相互转换使用
- do-whlie循环在实际使用场景中较少使用
无限循环语句
while(true)
for(;;)
循环的嵌套
循环的嵌套是指一个循环(以下由循环1代指)是另一个循环(以下由循环2代指)的循环体。
外层循环:循环2
内层循环:循环1
- 内层循环作为外层循环的循环体
- 两个循环,由外层循环控制循环次数,内层循环控制循环体的执行次数(具体情况由现场情况而言)
- 外层循环执行n次,内层执行m次,则内层的循环体会执行n*m次
- 不建议嵌套超过一个循环,多层循环的结构少见并且复杂
数组
数组的分类:
以下按照数组的维数来分类:
- 一维数组
- 二维数组
以下按照元素的类型来分类:
- 基本数据类型元素数组
- 引用数据类型元素数组
数组元素初始化之后的默认情况:
- 整数数组:默认值为:0
- 小数(浮点)数组:默认值为:0.0
- 字符数组:默认值为:0或'\u0000'
- 布尔数组:默认值为:false
- 引用数组:默认值为:null
如果数组为二维数组,则外层元素为null,内层元素为不存在,无法调用。
数组由以下几个元素组成
- 数组名
- 数组元素(即为数组中存储的元素)
- 数组中数值的编号(下标)
- 数组的长度(即为数组中存储的元素个数)
数组拥有以下特点:
- 数组中的元素在内存中是有序紧密排列的
- 数组一旦初始化完成,其长度不改变
一维数组
数组的概念:将多个相同类型的数值按顺序排列在一起的组合,并将这个组合命名。
可以将这个组合理解为一个容器、组合,在内存中会为这个组合开辟一个存储空间。
各类型数组初始化示例:
String[] arr = {"我", "爱", "你"};
prices = new double[]{20.32,43.21,43.22};
int arr[] = new int[]{1,2,3,4};
二维数组
二维数组可以将它看为数组的嵌套,因为从运行机制来说并没有多维数组。
实际上二维数组只是将一个一维数组作为另外一个一维数组的元素。
各类型数组初始化示例:
int arr2[][] = new int[][]{{1,2,3},{4,5},{6}};
String[][] arr3 = new String[4][3];
double[][] arr4 = new double[4][2];
方法
如果需要经常使用一段代码,那么建议直接将代码放在一个方法当中。等到需要用到这行代码时直接调用此方法即可。
方法的两大类
- 没有返回值的方法
- 有返回值的方法
没有返回值的方法
public static void 方法名(参数列表){
代码体;}
有返回值的方法
public static 数据类型 方法名(参数列表){
代码体;
return 数据类型对应的返回值;}
面向对象
初始面向对象
面向对象内容的三条主线
- Java类及类的成员:属性(重点)、方法、构造器;代码块(熟悉)、内部类
- 面向对象的特征:封装、继承、多态、(抽象)
- 其他关键字的使用:this、super、package、import、static、final、interface、abstract等
面向过程的编程(pop)vs 面向对象编程(oop)
用简单的语言描述二者的区别就是:
- 面向过程(Process-Oriented Programming):以函数为组织单位;是一种执行者思维,适合解决简单问题。扩展能力差、后期的维护难度大
- 面向对象(Object Oriented Programming):以类为组织单位。每种事务都具备自己的属性和行为或者说功能。
类的成员之一:属性
变量的分类:
- 按数据类型来分:基本数据类型(八种)、引用数据类型(数组、类、接口、枚举、注解、记录)
- 按照变量再类中声明的位置的不同:成员变量(属性)、局部变量(方法内、方法形参、构造器内、构造器形参、代码块内等)
属性的几个称谓:成员变量、属性、field(字段、域)
区分成员变量 vs 局部变量 他们的相同点:
- 变量声明的格式相同:数据类型 变量名 = 变量值;
- 变量都有其作用域。出了作用域就失效了
- 变量必须先声明后赋值
类的成员之二:方法(method)
使用方法的好处
- 方法的理解:“方法”是类或对象行为特征的抽象,用来完成某个功能操作
- 方法的好处:实现代码重用,减少冗余,简化代码
使用举例
-Math.random()的random()方法
-Math.sqrt()的sqrt()方法
-System.out.println()println()方法
-new Scanner(System.in) .nextInt()方法
-Arrays类中的binarySearch()方法、equals()方法
类的成员之三:构造器(constructor)
构造器的理解
constructor:建造、构造、建设
构造器的作用
- 搭配new关键字,创建类对象
- 再创建对象的同时,可以给对象的相关属性赋值
构造器的使用说明
- 构造器的声明格式:权限修饰符 类名(形参列表){ }
- 创建类以后,再没有显示提供任何构造器的情况下,系统默认提供一个空参的构造器,且构造器的权限与类声明的权限相同
- 如果类中显示声明构造器,系统不在提供默认的空参的构造器
- 一个类中可以声明多个构造器,彼此之间构成重载
封装性
面向对象特征之一:封装性
为什么需要封装?
理论上来说:
- 高内聚:类的内部数据操作细节自己完成,不允许外部干涉
- 低耦合:仅暴露少量的方法给外部使用,尽量方便外部调用
通俗的说:吧改隐藏的隐藏起来,该暴露的暴露出来
如何实现数据封装?
权限修饰符
Java规定了四种权限修饰符:
- private
- 缺省
- protected
- public
本类内部(private)、本包内(缺省)、其他包的子类(protected)、其他包非子类(public)
this关键字的使用
目前可能出现的问题?以及解决方案
当声明一个属性对应的SetXxx方法时,通过形参给对应的属性赋值。如果形参名和属性名同名,如何在方法中区分变量? 解决方案:使用this。使用this修饰的变量,表示属性,没有this修饰的变量,表示形参
this可以调用的结构
- 成员变量
- 方法
- 构造器
this的理解
当前对象(方法调用时)或当前正在创建的对象(在构造器调用时)
this调用属性和方法
针对于方法内的使用情况(非static修饰的方法)
继承性
面向对象特征之二:继承性
继承性的理解
-生活上:财产、血缘的继承
-代码层面
-自上而下:定义一个A类,在定义另一个B类时,发现B类的功能与A类相似,考虑B类继承于A类
-自下而上:定义了类B、C、C等,发现B、C、D有类似的属性和方法,则可以考虑将相同的属性和方法进行抽取,
封装到A类中,让类B、C、D继承于类A,同时类B、C、D中的相似的功能就可以删除了
继承性的好处
- 继承性的出现减少了代码的冗余,提高了代码的复用性
- 有利于功能的扩展
- 继承的出现让类于类之间产生了“is-a”的关系,为多态提供了前提
- 继承描述事务之间的所属关系“is-a”,父类更通用、一般,子类更具体
抽象类与接口
abstract的概念
抽象的
abstract可以用来修饰
类方法
具体使用
abstract修饰类
此类称为抽象类 抽象类不能实例化 抽象类包含构造器,子类对象实例化,需要直接或间接的调用到父类构造器 抽象类中可以没有抽象方法,有抽象方法所在的类,一定是抽象类
abstract修饰方法
此方法称为抽象方法 抽象方法只有方法的声明,没有方法体
接口的使用
接口的理解
接口的本质是契约、标准、规范
定义接口的关键字
interface
接口的内部结构的说明
可以声明:
属性:必须使用public static final修饰(全局变量)
方法:jdk8之前:只能声明抽象方法,修饰为public static
jdk8:声明静态方法、默认方法
jdk9:声明私有方法不可以声明:构造器、代码块等
类的多态
面向对象特征之三:多态性
如何理解多态?
一个事务的多种形态
Java中多态性的体现
子类对象的多态性:父类的引用指向子类的对象
多态性的应用
虚拟方法调用 在多态的场景下,调用方法时 编译时,认为方法是左边声明的父类的类型的方法(即被重写的方法) 执行时,实际执行的是子类重写父类的方法 简称:编译看左边,运行看右边
类的高级特性
static关键字的使用
static静态的
声明变量和方法时,加上static修饰,称为类变量和类方法(或静态变量和静态方法),和实例之间的共享
static用来修饰的结构
- 属性
- 方法
- 代码块
- 内部类
static修饰属性
复习:变量的分类
方式1:按照数据类型:基本、引用 方式2:按照类中声明的位置: 成员变量:按照是否使用static修饰进行分类使用static修饰的成员变量:静态变量、类变量
final关键字的使用
final的理解
最终的
final可以用来修饰的结构
- 类
- 方法
- 变量
具体说明
final修饰类
此类表示不能被继承 比如:String、StringBuffer、StringBuilder类
final修饰方法
表示方法不能被重写 比如:Object类中的getClass()
final修饰变量
即可以修饰成员变量,也可以修饰局部变量
类的成员之五:内部类
什么是内部类?
将一个类a定义在另一个类b里面,里面的那个类a叫做内部类(Inner Class),外面的类b叫(Outer Class)
为什么需要内部类?
当一个类只服务于另一个类时,推荐定义内部类,遵循高内聚、低耦合的面向对象开发原则
内部类的使用举例
Thread类内部声明了State类,表示线程的生命周期 HashMap类中声明了Node类,表示封装的Key和Value
内部类的分类
成员变量:直接声明在外部类的里面
异常
异常处理概述
什么是异常?
指的是程序在执行过程中,出现的非正常情况,如果不处理最终会导致jvm的非正常停止
异常抛出机制
java中把不同的异常用不同的类表示,一旦发生某种异常,就创建该异常类型的对象,并且抛(throw)。然后程序员可以捕获(catch)到这个异常对象,并处理; 如果没有捕获(catch)这个异常对象,那么这个异常对象将会导致程序终止。
如何对待异常
对于程序出现的异常,一般有两种解决方法:一是遇到错误就终止程序的运行。另一种方式是程序员在编写程序时,就充分考虑到各种可能发生的异常和错误,极力预防和避免。实在无法避免的,要编写相应的代码进行异常检测
方式一(抓抛模型):try-catch-finally
过程1:“抛”
程序在执行的过程中,一旦出现异常,就会在出现异常的代码处,生成对应异常类的对象,并将此对象抛出
一旦抛出,此程序就不在执行其它的代码了过程2:“抓”
针对于过程1中抛出的异常对象,进行捕获处理。此捕获处理的过程,就称为抓
一旦将异常进行了处理,代码就可以继续执行
基本结构
try{
...... //可能产生异常的代码
}
异常处理的方式2:throws
1. 格式:在方法的声明出使用“throws 异常类型1,异常类型2,...”2. 举例:
public void test() throws 异常类型1,异常类型2,...{
//可能存在编译时异常
}
是否真正处理了异常?
从编译是否通过的角度看,看成是给出了异常,万一要是出现时候的解决方案。此方案就是,继续往上抛(throws)
但是,此throws的方式,仅是将可能出现的异常抛给了此方法的调用者。此调用者任然需要考虑如何处理相关异常
从这个角度来看,throws的方式不算是真正意义上处理了异常
常用类
string类的理解(以jdk8为例说明)
类的声明
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence-final:String是不可被继承的
-Serializable:可序列化接口。凡是实现此接口的类的对象都可以通过网络或本地流进行数据的传输。
-Comparable:凡是实现此接口的类,其对象都可以比较大小。
内部声明的属性
jdk8中:
private final char value[];//储存字符串数据的容器
-final:指明此value数组一旦初始化,其地址就不可变jdk9开始:为了节省内存空间
private final byte[] value;2. 字符串常量的储存位置
-字符串常量都储存在字符串常量池(StringTable)中
-字符串常量池不允许存放两个相同的字符串常量
-字符串常量池,在不同的jdk版本中,存放位置不同
jdk7之前,字符串常量池存放在方法区
jdk7及之后,字符串常量池,存放在堆空间3. String的不可变性的理解
4. String实例化的两种方式
【面试题】
String s2 = new String("hello");在内存中创建了几个对象?
一个是堆空间中new的对象。另一个是在字符串常量池中生成的字面量5. String的连接操作:+
情况1:常量 + 常量 :结果仍然储存在字符串常量池中,返回此字面量的地址。注:此时的常量可能是字面量,也可能是final修饰的常量
情况2:常量 + 变量 或 变量 + 常量 :都会通过new的方式创建一个新的字符串,返回堆空间中此字符串对象的地址值
情况3:调用字符串的intern() :返回的是字符串常量池中字面量的地址
(了解)情况4:concat():无论是常量调用方法,还是变量调用方法,无论参数是参量还是变量,调用完concat()方法都会返回一个新new的对象6. String的构造器和常用方法
6.1 构造器
public String():初始化新创建的String对象,以使其表示空字符序列
public String(String original):初始化一个新创建的String对象,使其表示一个与参数相同的字符序列
public String(char value[]):通过当前参数中的字符数组来构造新的String
public String(char value[], int offset, int count):通过字符数组的一部分来构造新的String
public String(byte bytes[]):通过使用平台的默认字符集解码当前参数中的字节数组来构造新的String
public String(byte bytes[], String charsetName):通过使用指定的字符集解码当前参数中的字节数组来构造新的String
针对于StringBuilder来说:
内部属性有:
char[] value;//储存字符序列
int count;//实际储存的字符的个数StringBuilder sb1 = new StringBuilder();//char[] value = new char[16];
StringBuilder sb1 = new StringBuilder("abc");//char[] value = new char[16+"abc".length()];sb1.append("ac");//value[0] = 'a';value[1] = 'c';
sb1.append("b");//value[2] = 'b';当count超过value.length()时,就需要扩容:默认扩容为原容量的2倍+2,并将原有value数组中的元素复制到新的数组中
jdk8之前的api
system类的currentTimeMillis
获取当前时间对应的毫秒数,long类型,时间戳:是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起到现在的总秒数 当前时间与1970年1月1日0时0分0秒之间的毫秒数 常用来计算时间
两个date类
java.util.Date 两个构造器的使用 两个方法的使用 java.sql.Date:对应数据库中的date类型