1、java简单概述
java是一门面向对象的语言,由sun公司Green项目小组的帕特里克、詹姆斯·高斯林、麦克·舍林丹开发出来的,前期java语言的名字叫做Oak,后面在注册商标的时候发现Oak这名字被占用又更名为java语言,于1995年5月23日java语言正式问世。
java语言的特点
Java具有简单性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点 。
java的注释
//单行注释
/*/多行注释
/ */文档注释
2、java开发环境搭建
(1)首先按住win+r键输入cmd进入命令行窗口,在里面输入java -varsion 没安装的话会出现如下所示命令不正确,接下来我们来进行安装。
(2)下载jdk
百度搜索 https://www.oracle.com/index.html
找到Developers点进去
主页上方找到Downloads,选择JavaSE
页面中部找到Java SE 8,点击下面的downloads。
点击JDK Download链接。
根据自己电脑系统选择需要的版本点击下载,本人选择是windows x64位的。
点击之后会弹出来一个框框,然后勾选框框
点击下载之后会弹出如下界面提示你注册一个Oracle账户,点击创建账户
创建账户完成之后会自动下载
[图片上传失败...(image-e139d0-1608705598522)]
下载完成后右击选择安装
[图片上传失败...(image-399183-1608705598522)]
简单式操作,一直点击下一步即可
当安装成功之后我们再去cmd运行 指令 java - version 出现对应的jdk版本号
2.1jdk简单介绍
jdk(Java Development Kit)是java的开发工具包,是编写java程序的开发环境,是java的核心包,同时包含了运行环境jre(Java Runtime Environment)。
jdk下面的文件介绍
bin:存放jdk的一些工具。
lib:类库,常用于放jar包。
jre:运行环境包含java虚拟机。
include:里边包含头文件,支持Java本地接口和Java虚拟机调试程序接口的本地代码编程。
demo 其中包含源代码的演示举例程序集。
DB:一个纯Java实现,开源的数据库管理系统(DBMS)java的内嵌数据库。
src:存放Java的源代码。
2.2cmd命令行运行java程序
新建一个txt,后缀名保存为java
2.3 doc 常用的指令
cls 清除页面的内容
java -jar jar文件名.jar 运行jar文件
d: ----进入指定的盘符
cd 空格 文件夹名字 ---进入文件
javac java文件名字.java 编译java文件
java java文件名 执行java文件
因为没配置jdk环境变量所以无法编译java文件.
我们来配置一下java jdk环境变量
找到自己电脑的此电脑
点击属性
点击环境变量
新建一个一个用户变量,变量值就是你的jdk安装路径,一般默认在C:\Program Files\Java\jdk1.8.0_261,
然后找到系统变量找到Path并选中,点击编辑
点击新建输入一下
%JAVA_HOME%\bin
%JAVA_HOME%\jre\bin
然后来看一下效果吧
发现中文乱码了
解决办法
右击java文件 > 记事本打开 > 另存为 选择编码为ANSI就可以了
当然可以直接在你的java文件下 在搜索栏输入cmd也可以编译执行java文件
3、java开发工具
常见的有eclipse、myeclipse、IDEA。
个人认为 IDEA比较适合开发者使用,因为功能很强大。
初学者的话使用eclipse 比较方便
3.1下载安装eclipse
打开百度在地址栏输入:http://www.eclipse.org/downloads/
点击Download进行下载
下载完成,解压
选择eclipse.exe点击
运行到如下图:
点击Browse可以切换工作空间
选择好工作空间之后选择luanch就行了
进入到软件里面了会有一个欢迎界面
3.2新建一个java工程项目
在右上角找到file 右击选择Java Project
点击finsh
src是存放java文件的地方
3.3使用eclipse执行一个java文件并运行
选中src右击鼠标,找到class并点击
点击运行后代码没错误的话就会打印出来一句话
3.4eclipse常用的快捷键
使用快捷键可以大大提高写代码的效率。
批量修改代码:alt + shift + r
代码返回值接收:ctrl+/
快速输入主方法:main
快速输入System.out.println();:syso 或者sout
快速输入for:for
查看关键字的底层源代码:ctrl+鼠标右键
代码格式化: ctrl+shifr+f
快速导包:ctrl+shift+o
快速单行注释:ctrl+shift+c
快速多行设置:ctrl+shift+o
提示代码:ctrl+1
如果每次觉得按ctrl+1太麻烦的话可以按如下操作
点击apply继续点击 Apply and close 就行了。
3.5、package(包)
3.5.1、包的作用
创建java类的时候不可以使用重复的名字,包恰好解决了这个问题,也限制了类的访问权限。
3.5.2包的创建
选中src右击点击Package
3.5.3、包的命名规则
package必须是程序中可执行的第一行代码
package语句只能有一句
package命名要求包含的所有字符均为小写,同时不能有特殊字符
package可以有多层,每一层有.隔开,例如:package china.hubei.wuhan;(China是一个文件夹,hubei是china下的一个文件夹,wuhan是hubei文件夹下的一个文件夹
package语句后面的分号不要掉。
包的路径符合所开发的系统模块的定义,比如生产对生产,物资对物资,基础类对基础类。
如果定义类的时候没有使用package,那么java就认为我们所定义的类位于默认包里面(default package)。
团队开发包的命名规范
team.团队名.项目名.模块名.…
公司开发包的命令规范
com.公司名.项目名.模块名.....
3.5.4、(import)导包
如果在不同包想使用指定的类可以使用impotr关键字进行导包。
语法:import 包名.指定的类名
4、变量
4.1什么是变量
变量顾名思义就是可变的量,用来命名数据的标识符合。
4.2变量的定义
用变量来表示一个人的年龄。
int age = 20;
int --数据类型
age --变量名
= --赋值
20 --变量的值
;--结束
以上定义了一个变量并把值20赋值给age。
定义变量是用来存储东西的,会在jvm(java虚拟机)的栈空间开辟一个内存地址,通过变量名字的引用在栈空间查找到对应的值。
4.3八大基础数据类型
在java中存在八大数据类型分别是byte、short、int、long、float、double、boolenan、char。
八大基本数据类型又分为四种类型
整型:byte、short、int、long
浮点型:float、double
布尔型:boolean
字符型:char
4.4八大基本数据类型的默认值和取值范围
4.5数据类型转换
举一个生活中的例子说明数据类型
把大类型数据比作一个装满水的大水杯,小数据类型比作一个装满水的小水杯,小杯子往大杯子倒一次水大杯子的水怎么都不会满,而大杯子往小杯子倒水小杯子的水会溢出。
数据类型从小到大排序
转换规则:大类型转小类型需要强制转换,小类型转大类型自动转换。
小类型转大类型
因为int比long的数据类型小所以可以自动转换
大类型转小类型
数据类型 =(需要转换成的类型)变量
4.6、变量的命名规则
①变量命名只能使用字母 数字 下划线
③变量第一个字符 不能使用数字
④不能使用关键字
4.7、变量类型
类变量:独立于方法之外的变量,用 static 修饰。
实例变量:独立于方法之外的变量,不过没有 static 修饰。
局部变量:类的方法中的变量。
从上图可以看出类变量被类包含在{}里面可以通过变量名在类包含的任意地方使用也可以通过类名.类变量名使用。
实例变量需要实例化之后才能使用。
局部变量在方法里面可以直接使用。
4.8、表达式和块
以;结尾的就是一个表达式。
以{}包裹起来的就是一个块。
5、运算符
在java当中运算符分为算术运算符,关系运算符,位运算符,逻辑运算符,赋值运算符。
5.1算术运算符
常见的算术运算符有+、-、*、/、++、--
++和--的区别
++在变量的前面先赋值后运算,++在变量的后面先运算后赋值。
5.2关系运算符
常见的关系运算符
返回值为true 金额f alse
> 大于
>= 大于或等于
< 小于
<= 小于或等于
== 是否相等
!= 是否不等
5.3逻辑运算符
短路&& 与 和 长路& 与
无论长路与还是短路与,两边的运算单元都是布尔值,都为真时,才为真,任意为假,就为假。
区别
长路与 两侧,都会被运算
短路与 只要第一个是false,第二个就不进行运算了
|| 长路或 |短或
无论长路或还是短路或,两边的运算单元都是布尔值,都为假时,才为假,任意为真,就为真
区别
长路或 两侧都会被运算。
短路或 只要第一个是true的,第二个就不进行运算了。
! 非
真变假假变真
异或
异或^
不同,返回真
相同,返回假
5.4、三元运算符
语法:表达式?值1:值2
如果表达式为真 返回值1
如果表达式为假 返回值2
5.5、赋值运算符
常见的有=、+=、-=、*=、/=、%=。
public class AssignmentOperatorTest01 {
public static void main(String[] args) {
//基本的赋值运算符
int i;
i = 10;
System.out.println("i = " + i);
i = 100;
System.out.println("i = " + i);
//扩展的赋值运算符
int x = 10;
x += 1; //等同于x = x + 1
System.out.println("x = " + x); //11
int y = 10;
y -= 1; //等同于y = y - 1
System.out.println("y = " + y); //9
int z = 10;
z *= 2; //等同于z = z * 2
System.out.println("z = " + z); //20
int m = 10;
m /= 3; //等同于m = m / 3
System.out.println("m = " + m); //3
int n = 10;
n %= 3; //等同于 n = n % 3
System.out.println("n = " + n); //1
}
}
6、输入和输出
6.1、输入
在java当中使用Scanner类可以进行输入
使用Scanner的步骤:
1、创建扫描器(Scanner)
Scanner scanner = new Scanner(System.in);
2、使用import导包
import java.util.Scanner;
3、接收基本数据类型
next()和nextLine()的区别
next()方法在读取内容时,会过滤掉有效字符前面的无效字符,只有在读取到有效字符之后,next()方法才将其后的空格键、Tab键或Enter键等视为结束符;所以next()方法不能得到带空格的字符串。
nextLine()方法字面上有扫描一整行的意思,它的结束符只能是Enter键,即nextLine()方法返回的是Enter键之前没有被读取的所有字符,它是可以得到带空格的字符串的。
6.2、输出
System.out.println("打印的内容换行");
System.out.print("打印的内容不换行");
7、控制流程语句
7.1、if语句
if用来条件判断
if(表达式1){
表达式2;
}
表达式1的值为true才会执行表达式2的值。
单个if
条件为true才会往下执行
7.2、if-else语句
if(表达式1){
表达式2;
}else{
b表达式3;
}
表达式1的值为true才会执行表达式2的值,为false执行表达式三的值。
条件为假所以才执行else后面的表达式。
7.3 if-elseif-else语句
elseif用于多条件判断
7.4、switch语句
switch case 语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支。
语法:
每个个表达式结束,都应该有一个break;;
switch在jdk1.7之前只可以使用基本数据类型,jdk1.7了可以使用字符串(String),编译后是把String转化为hash值,其实还是整数。
switch(变量){
case value :
//语句
break;
case value :
//语句
break;
//你可以有任意数量的case语句
default :
//语句
}
7.5、while 语句
语法:while(条件){
表达式;
}
条件为true时会一直执行表达式的内容;
7.6、do-while语句
条件为true时 重复执行,至少会执行一次
do-while与while的区别在于,dowhile先执行一次再做判断。
7.7、for语句
语法
for (初始化表达式,布尔表达式,更新表达式){
表达式;
}
7.8、break语句
break常用于结束循环。
package com.lc;
public class breaks {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
System.out.println(i);
//当循环条件等于10的时候会终止循环
if(i==10) {
break;
}
}
}
}
运行结果
0
1
2
3
4
5
6
7
8
9
10
7.9、continue语句
continue语句则是用来终止当前本次循环,直接进入下一次循环继续执行。
8、面向对象
8.1、面向对象的概念
面向对象是一种以对象为中心的编程思想,万物皆对象,通过面向对象我们可以将现实中存在的事物抽象成对象。
有面向对象的语言,也有面向过程的语言,面向过程就是析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
8.2、类和对象
什么是类?
具有共同特征的事物。
类是一个模板,描述着对象的行为和方法。
什么是对象?
对象是类的实例,对象具有行为和属性。
类和对象之间的关系?
类的实例化就是对象,对象的抽象就是一个类。
类的命名规范
首字母大写,多个单词的首字母大写。
不能以关键字命名。
不能以特殊符号命名。
类由一对花括号包裹着
我们通过代码来创建一下类和对象
package com.oop;
public class person {
/**
* 属性
*/
//名字
String name;
//性别
String sex;
//年龄
int age;
//家庭住址
String address;
/**
* 行为
*/
//自我介绍
public void show () {
System.out.println("我叫.....................");
}
}
package com.oop;
public class TestPerson {
public static void main(String[] args) {
//实例化一个对象
//对象p的引用指向person类
person p = new person();
}
}
8.2.1、访问修饰符
在java中存在四种访问修饰符:public(公共的)、private(私有的)、protected (受保护的)、default(默认的可以不写)。
[图片上传失败...(image-724e52-1608705598523)]
8.2.2、属性
属性分为类属性和对象属性。
类属性:被关键字static修饰过的,所有的对象,都共享这个属性。
对象属性:不同对象的值都是不一样的。
//定义一个类属性
static String name;
//属性也可以在定义的时候初始化
static String name ="张三";
//定义个对象属性
public int age;
private String name;
protected int pwd;
8.2.3、访问属性
类属性可以通过类名.属性名进行访问也可以实例化对象进行访问,对象属性则要实例化对象才能访问。
8.2.4、方法
常见的就是main方法:public static void main (String [] args ){}
程序的主入口。
方法的命名规范
方法的名字的第一个单词应以小写字母作为开头,后面的单词则用大写字母开头。
方法的语法
修饰符 返回值 方法名 (){}
方法的返回值需要返回对应的类型,方法的返回参数谁调用谁就要传对应的参数给方法。
实例
8.2.5、方法参数返回
参数的返回
package com.oop;
public class method {
public static void main(String[] args) {
method m =new method();
m.show();
String show1 = m.show1();
System.out.println(show1);
m.show2("有参无返回");
String show3 = m.show3("有参有返回");
System.out.println(show3);
}
//无参无返回
public void show () {
System.out.println("我是无参无返回方法!");
}
//无参有返回
public String show1 () {
return "无参有返回";
}
//有参无返回
public void show2(String str) {
System.out.println(str);
}
//有参有返回
public String show3(String ss) {
return ss;
}
}
运行结果
我是无参无返回方法!
无参有返回
有参无返回
有参有返回
8.2.6、方法重载
方法重载就是可以在一个类中定义同名的方法,方法的返回值参数不同。
规则:同名不同参与返回类型无关。main方法也可以重载。
实例:
8.2.7、构造方法
构造方法分为有参和无参,是用来实例化对象用的,如果在类中没有写构造方法,系统会默认调用无参构造方法,构造方法也是可以重载的,但是不可以重写。
构造方法语法:修饰符 类名 (){ }
package com.oop;
public class gouzao {
//创建一个无参构造方法
public gouzao () {
System.out.println("我是五参数构造方法!");
}
//有参数构造方法
public gouzao (String name) {
System.out.println("我叫:"+name);
}
public static void main(String[] args) {
gouzao gz = new gouzao("张三");
}
}
运行结果
我叫:张三
8.3、面向对象的三大特征
面向对象的三大特征:封装、继承、多态。
8.3.1、封装
简单来说封装就是将数据保护起来,只有通过特定的方法才可以进行访问。
封装的好处:
1、良好的封装能够减少耦合。
2、类内部的结构可以自由修改。
3.、可以对成员变量进行更精确的控制。
4.、提高数据安全
实现封装的步骤
①属性设置为私有化(private)。
②提供getset方法(取值、赋值方法)。
因为对属性进行封装了,外部是不能进行访问的,所以需要提供getset方法。
实例
package com.oop;
public class fengzhuang {
//属性私有化
private String name;
private String sex;
//get(取值) set(赋值)
public String getName() {
return name;
}
public void setName (String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
package com.oop;
public class Test {
public static void main(String[] args) {
fengzhuang ff = new fengzhuang();
//通过set方法设置值
ff.setName("张三");
ff.setSex("男");
//通过get方法取值
System.out.println("姓名:"+ff.getName()+"性别:"+ff.getSex());
}
}
输出结果
姓名:张三性别:男
8.3.2、继承
继承在生活中最常见的就是子承父业。
继承的语法:class 子类 extends 子类 { }
注意:在java当中继承只可以单继承,换句话来说就是儿子只能有一个爸爸。不能进行多继承。
继承的好处:
①子类可以拥有父类非私有(private)的属性和方法。
②子类可以扩展出新的属性和方法。
③子类可以以自己的方式实现父类的方法。
④提高了类之间的耦合性。
package com.oop;
import com.lc.breaks;
public class extendss {
public static void main(String[] args) {
a a1 = new a();
b b = new b();
a1.show("张三");
b.show("李四");
}
}
/*创建一个a类*/
package com.oop;
import com.lc.breaks;
public class extendss {
public static void main(String[] args) {
a a1 = new a();
b b = new b();
a1.show("张三");
a1.s("李四");
b.show("李四");
}
}
/*创建一个a类*/
class a {
private String name;
public void show (String name) {
System.out.println("我叫:"+name);
}
void s(String name) {
this.show(name);
}
}
/*创建一个b类*/
class b extends a{
private String name;
public void show () {
super.show(name);
}
}
我叫:张三
我叫:李四
我叫:李四
上面代码中的super和this都是关键字。
super:对父类进行访问。
this:代表自己本身。
8.2.3、多态
多态:同一行为具有不同的表现方式。
举个例子:人吃饭,可以站着吃,躺着吃,想怎么吃就怎么吃。
多态的优点:
1、消除类型之间的耦合关系
2.、可替换性
3.、可扩充性
4、 接口性
5、灵活性
6、简化性
实现多态的三个条件:
1、继承
2、重写
3、父类引用指向子类对象
实例
package com.oop;
//创建一个动物
public abstract class Animal {
//吃的方法
abstract void eat();
public static void main(String[] args) {
show(new brid());
show(new cat());
//向上转型 父类引用指向子类对象
Animal animal = new cat();
animal.eat();
//向下转型 子类引用指向父类对象
cat c = (cat)animal;
c.eat();
}
/*类型判断*/
public static void show(Animal a) {
//如果 brid 是动物类型 进行强转
if(a instanceof brid) {
brid b = (brid)a;
b.eat();
//如果 cat 是动物类型 进行强转
}else if(a instanceof cat) {
cat c=(cat)a;
c.eat();
}
}
}
class brid extends Animal {
//重写父类的方法
@Override
void eat() {
System.out.println("小鸟吃虫子......");
}
}
class cat extends Animal {
//重写父类的方法
@Override
void eat() {
System.out.println("猫吃老鼠......");
}
}
小鸟吃虫子......
猫吃老鼠......
猫吃老鼠......
猫吃老鼠......
8.4、抽象
抽象:无法描述的类就是抽象类。
抽象类的特征
抽象类不能实例化,子类可以进行实例化。
抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。
抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
实例
8.5、final关键字
final代表最终的不可变的。
final修饰的类无法被继承。
final修饰的方法无法被子类重写
final修饰的变量只能赋值一次,之后就不能改变了。
[图片上传失败...(image-f941d4-1608705598523)]
final修饰的引用只有一次执行对象的机会
8.6、接口
接口是一种规范。
加粗样式
接口和类的区别
接口不能用于实例化对象。
接口没有构造方法。
接口中所有的方法必须是抽象方法。
接口不能包含成员变量,除了 static 和 final 变量。
接口不是被类继承了,而是要被类实现。
接口支持多继承
接口特性
接口中的方法和变量都被隐式指定为抽象方法和常量,简单来说就是接口中的方法是抽象方法变量是常量。
接口中的方法只能由子类实现。
接口中的方法都是public(公开的)
抽象类和接口的区别
1、抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
2、 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
3、接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
4、 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
JDK 1.8 以后,接口里可以有静态方法和方法体了。
接口的声明
修饰符 interface 接口名称 extends 其他的接口名称
实现接口
类实现接口要实现所有的方法,否则声明为抽象类
implements 实现接口的关键字放在类的后面
实现接口需要注意:一个类只可以继承一个类,但是可以实现多个接口,接口之间可以继承。
8.7、内部类
内部类简单来说就是在类的内部还有类。
内部类分为四种:成员内部类、局部内部类、匿名内部类和静态内部类。
成员内部类
成员内部类在一个类的里面,而这个包裹着内部类的类叫做外部类,内部类可以访问外部类的所有成员属性和成员方法。
当外部类方法和内部类方法变量同名通过this区分。
外部类.this.成员变量
外部类.this.成员方法
package com.oop;
public class waibu {
public waibu (String name) {
this.name = name;
}
static String name="张三";
class neibu{
public void show () {
System.out.println(name+"喊李四出去打麻将............");
}
}
public static void main(String[] args) {
waibu waibu = new waibu("zs");
neibu name = waibu.new neibu();
name.show();
}
}
结果
zs喊李四出去打麻将............
内部类访问外部类可以随心所欲的访问,而外部类访问内部类则先需要创建一个内部类对象,再通过指向对象的引用进行访问。
package com.oop;
public class wn {
public wn() {
}
class nb{
public void name() {
System.out.println("我是内部类!");
}
}
public static void main(String[] args) {
//首先创建一个外部类对象
wn w = new wn();
//再通过对象指向创建一个内部类就可以访问内部类的属性方法了。
wn.nb n = w.new nb();
n.name();
}
}
结果
我是内部类........
局部内部类
局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。
局部类不能有 public、protected、private 以及 static 修饰符的。
package com.oop;
class jbb{
class jbs{
public void names() {
System.out.println("我是局部内部类");
}
}
public static void main(String[] args) {
new jbb().new jbs().names();
}
}
运行结果
我是局部内部类
匿名类
匿名类指的是在声明一个类的同时实例化它,使代码更加简洁精练。
package com.oop;
public abstract class nm {
abstract void show();
public static void main(String[] args) {
new nm() {
//声明的时候同时实例化
@Override
void show() {
System.out.println("我是匿名类!!!");
}
}.show();
}
}
运行结果
我是匿名类!!!
静态内部类
静态内部类定义在类的里面,不需要依靠外部类,不能使用外部类非静态的属性和方法
package com.oop;
public class jt {
public static void main(String[] args) {
jt.jtnb j = new jt.jtnb();
j.name();
}
static class jtnb{
public void name() {
System.out.println("静态内部类.....");
}
}
}
运行结果
静态内部类......
8.8、Object类
obnject类是所有类的父亲,我们在创建类的时候都默认基础object类。
8.8.1、equals、hashcode方法
用来判断两个对象是否相等,默认比较对象的内存地址。
因为equals没有重写所以默认比较的是内存地址,返回false
package com.oop;
public class equalss {
String name;
int age;
public equalss(String name,int age) {
this.name=name;
this.age=age;
}
public static void main(String[] args) {
equalss e1 = new equalss("张三", 20);
equalss e2 = new equalss("张三", 20);
System.out.println(e1.equals(e2));
}
}
运行结果
false
重写了equals之后比较的是内容所以返回true,记得重写了equals方法必须重写hashcode方法。
如果重写equals后,如果不重写hashcode,则hashcode就是继承自Object的,返回内存编码,这时候可能出现equals相等,而hashcode不等,你的对象使用集合时,就会等不到正确的结果
package com.oop;
public class equalss {
String name;
int age;
/*重写equals*/
@Override
public boolean equals(Object obj) {
if(obj instanceof equalss) {
equalss e = (equalss)obj;
if(this.name.equals(e.name)) {
return true;
}
if (this.age==e.age) {
return true;
}
}
return false;
}
/*重写hashcode*/
@Override
public int hashCode() {
int hash = 17;
hash = hash*31+name.hashCode();
hash = hash*31+age;
return hash;
}
public equalss(String name,int age) {
this.name=name;
this.age=age;
}
public static void main(String[] args) {
equalss e1 = new equalss("张三", 20);
equalss e2 = new equalss("张三", 20);
System.out.println(e1.hashCode());
System.out.println(e2.hashCode());
System.out.println(e1.equals(e2));
}
}
运行结果
24037916
24037916
true
8.8.2、toString方法
所有的类都有toString方法。
toString()的意思是字符串的形式返回当前对象的信息。
package com.oop;
public class toStrings {
public String name;
@Override
public String toString() {
// TODO Auto-generated method stub
return "name="+name;
}
public static void main(String[] args) {
toStrings t = new toStrings();
System.out.println(new toStrings().name="张三".toString());
}
}
运行结果
张三
8.8.3、finalize方法
当一个对象没有任何引用指向的时候,它就满足垃圾回收的条件
当它被垃圾回收的时候,它的finalize() 方法就会被调用。
package com.oop;
import com.lc.fori;
public class finalz {
@Override
protected void finalize() throws Throwable {
System.out.println("回收对象...............");
}
public static void main(String[] args) {
finalz finalz = new finalz();
//对象指向null满足垃圾回收机制
finalz=null;
//调用垃圾回收方法
System.gc();
}
}
运行结果
回收对象...............
8.9、单例模式
单例模式又叫做 Singleton模式,指的是一个类,在一个JVM里,只有一个实例存在,也就是说只能实例化一个对象。
饿汉单例模式
通过调用getInstance方法创建一个对象,每一次是获取同一个对象,无论如何都会创建一个对象。
package com.oop;
public class danli {
//私有化构造方法使得在外部无法实例化对象
int count =0;
private danli () {
count++;
System.out.println("无参构造方法被调用了:"+count+"次");
}
//准备一个类属性指向实例化对象,因为类属性只有一个
private static danli dan =new danli();
public static danli getInstance() {
return dan;
}
public static void main(String[] args) {
danli dan = danli.getInstance();
danli dan1 = danli.getInstance();
}
}
运行结果
无参构造方法被调用了:1次
懒汉单例模式
package com.oop;
public class danli {
//私有化构造方法使得该类无法在外部通过new 进行实例化
private danli(){
}
//准备一个类属性,用于指向一个实例化对象,但是暂时指向null
private static danli instance;
//public static 方法,返回实例对象
public static danli getInstance(){
//第一次访问的时候,发现instance没有指向任何对象,这时实例化一个对象
if(null==instance){
instance = new danli();
}
//返回 instance指向的对象
return instance;
}
}
直接new会报错
通过getinstace方法才能实例化,并且实例化的是同一个对象。
8.10、static 关键字 和static块
static是一个关键字可以用来修饰变量、方法、代码块等。
在java当中凡是被static修饰的都是与类相关,可以直接通过类名.访问相对应的变量、方法、代码块。
static修饰变量和方法
static修饰代码块
从以下代码看出来static修饰的代码块优先级高于main方法。
9、数组
9.1、数组的概念
保存一个数据我们可以使用变量进行保存,当我们保存多个数据的时候变量就不能满足我们的需求了,我们可以使用数组来进行多个数据的保存。
数组就是一个固定长度包含了相同类型的数据容器。
9.2、数组的定义
当我们创建一个数组,jvm会在内存开辟一个内存空间用来保存数据。
分配空间并同时赋值
//第一种写法
int [] arr = {1,2,3};
//第二种写法
int []arr = new int []{1,2,3};
//第三种写法
int []arr = new int [3]{1,2,3};
分配完空间再赋值
int [] arr = new int [2];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
9.3、访问数组
在java当中我们通过数组的下标对数组元素进行访问,下标从0开始。
假如我们这里有个数组:int [] arr ={1,2,3};
这个数组的长度为3,下标因为是从0开始的,所以他的最大下标是2.
package com.arr;
public class arr1 {
public static void main(String[] args) {
//创建一个数组长度为4
int [] arr = {10,20,30,40};
//取数组最后一个下标的值,也就是3
System.out.println(arr[3]);
}
}
结果:40
9.4、遍历数组
数组有一个length表示数组的长度
9.5、数组的特点
优点:可以通过索引值访问任何的数组元素, 可以实现随机的访问。
缺点:插入/删除元素时, 需要扩容, 复制或者移动大量的元素, 效率比较低。
应用场景:适用于以查询访问为主, 很少进行插入/删除操作的情况。
9.6、可变长度参数
变长参数
可变长参数用来接收任意个数据
-
- 定义可变长参数
方法名( 参数类型 参数名, 参数类型 ... 可变长参数名)
*规则:
(1) 可变长参数最多只能有一个
(2) 方法参数列表如果有多个参数, 可变长参数只能放在参数列表的最后
(3) 在方法体中, 可以把可变长参数当作数组使用
(4) 在调用方法时,可以传递任意个数, 也可以传递一个数组
-
9.6、数组扩容
当我们定义好一个数组并分配好空间之后,数组的长度就是固定了的,如果我们想在数组中存放更多的数据,就需要对数组进行扩容。
package com.arr;
public class kuorong {
/**
* 数组的扩容
* @param args
*/
public static void main(String[] args) {
//定义一个数组并分配空间
int [] array = new int[5];
System.out.println("array数组扩容前的长度是:"+array.length);
//定义一个比原数组的空间大的新数组
//假设将新数组扩容1.5倍
int newarr [] = new int [array.length * 3/2];
//把原来数组的内容复制到新数组
for (int i = 0; i < array.length; i++) {
newarr[i] = array[i];
}
//把原来数组指向新的数组
array=newarr;
System.out.println("array数组扩容后的长度是:"+array.length);
}
}
输出结果
array数组扩容前的长度是:5
array数组扩容后的长度是:7
9.7、对象数组
数组元素是一个对象, 数组中存储的是引用类型数据
数组元素实际上存储的是对象的引用
package com.arr;
public class Person {
private String name;
private String sex;
public Person(String name, String sex) {
super();
this.name = name;
this.sex = sex;
}
public void eat() {
System.out.println(name+","+sex+"正在吃饭。。。。");
}
public static void main(String[] args) {
//创建一个对象数组
Person [] persons = new Person[3];
//为对象数组赋值
persons[0]= new Person("张三", "男");
persons[1]= new Person("李四", "男");
persons[2]= new Person("王二", "男");
//遍历对象数组
for (int i = 0; i < persons.length; i++) {
//让数组的每一个人都能吃到饭
persons[i].eat();
}
}
}
运行结果
张三,男正在吃饭。。。。
李四,男正在吃饭。。。。
王二,男正在吃饭。。。。
9.8、数组排序
冒泡排序
思路:从前向后两两比较,如果前面的数大于后面的数就交换,如果有n个数,需要比较n-1轮。
假设有一个数组:int [] arr = {50,30,10};
进行第一轮比较:50大于30,交换到30的后面 30,50,10
50大于10,交换到10的后面
第一轮排序结果为:30,10,50
进行第二轮比较:30大于10,30移动到10的后面
排序结果为10,30,50
package com.arr;
public class maopao {
public static void main(String[] args) {
int [] arr = {10,30,5,8,2};
//外层for循环获得arr数组的长度
for (int i = 0; i < arr.length; i++) {
//内层循环控制数组循环比较的次数
for (int j = 0; j < arr.length-1-i; j++) {
//如果左边的值大于右边的值就往后移
if(arr[j]>arr[j+1]) {
int temp = arr[j];
arr[j]= arr[j+1];
arr[j+1]= temp;
}
}
}
/*打印排序的结果*/
for (int i : arr) {
System.out.println(i);
}
}
}
9.9、二维数组
二维数组,里面的每一个元素,都是一个一维数组,所以二维数组又叫数组的数组。
9.10数组工具类
Arrays是针对数组的工具类,可以进行 排序,查找,复制填充等功能。 大大提高了开发人员的工作效率。
package com.arr;
import java.util.Arrays;
public class gongju {
public static void main(String[] args) {
int arr [] = {10,20,30,100,5,2,1};
/*使用工具类对数组进行排序*/
Arrays.sort(arr);
/*相当于遍历数组*/
System.out.println(Arrays.toString(arr));
/*用工具类赋值数组*/
//Arrays.copyOfRange(original, from, to)
//original-原数组 from-开始位置 to-结束位置
int [] newarr =Arrays.copyOfRange(arr, 0, 6);
System.out.print("复制过后的新数组:");
System.out.println(Arrays.toString(arr));
//查找数组元素的位置
//搜索之前先排序
Arrays.sort(arr);
//数字30出现的位置
System.out.println("数字30出现的位置"+Arrays.binarySearch(arr, 30));
}
}
10、数字和字符串
10.1、装箱和拆箱
简单来说装箱就是把基本类型数据转换成包装类,拆箱就是把包装类转换成基本类型数据。
每个基本类型数据都有对应得包装类。
number类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
boolean类型 | 包装类 |
---|---|
boolean | Boolean |
字符型 | 包装类 |
---|---|
char | Character |
package com.api;
public class baozhuang {
public static void main(String[] args) {
//装箱 --包基本类型数据转换成包装类
int i = 100;
Integer j = new Integer(i);
System.out.println(j);
//拆箱 --包装类转换成基本类型
Double d = new Double(50.0);
double d1 = d.intValue();
System.out.println(d1);
//自动装箱、拆箱 --不需要调用构造方法 通过= 进行自动装箱、拆箱
//自动装箱
float f = 10f;
Float f1 = f;
System.out.println(f1);
//自动拆箱
Character c = 'a';
char c1 = c;
System.out.println(c1);
}
}
运行结果
100
50.0
10.0
a
10.2、Math类
java.lang.Math提供了一些常用的数学运算方法,并且都是以静态方法的形式存在。
package com.api;
import java.util.Random;
public class strings {
public static void main(String[] args) {
double i = 4.6;
//Math.round() 四舍五入
System.out.println(Math.round(i));
//Math.random() 取一个0到1之间得随机浮点数,取不到取1
System.out.println(Math.random());
//Math.random()*10 取一个1到10之间得随机整数,取不到取10
int r =((int)(Math.random()*10));
System.out.println(r);
int j = 100;
//Math.abs() 求绝对值
System.out.println(Math.abs(j));
// Math.acos() 返回三角余弦
double d = 50;
System.out.println(Math.acos(d));
// Math.pow(参数1, 参数2)返回第一个参数的第二个参数次幂的值。
double d1 = 10,d2=3;
//10得3次幂
System.out.println(Math.pow(d1, d2));
//Math.sqrt()返回正确舍入的 double 值的正平方根
System.out.println(Math.sqrt(9));
}
}
运行结果
5
0.22821566498364498
4
100
NaN
1000.0
3.0
10.3、字符(Character)
package com.api;
public class characters {
public static void main(String[] args) {
//character字符操作
//判断是否是一个字符,是返回true,不是返回false
System.out.println(Character.isLetter('a'));
//判断是否是数字,是返回true,不是返回false
System.out.println(Character.isDigit('s'));
//判断字符是否是大写,是返回true,不是返回false
System.out.println(Character.isUpperCase('S'));
//判断字母是否是小写,是返回true,不是返回false
System.out.println(Character.isLowerCase('s'));
//转换成小写
System.out.println(Character.toLowerCase('A'));
//小写转换成大写
System.out.println(Character.toUpperCase('a'));
}
}
运行结果
true
false
true
true
a
A
10.4、String(字符串)
字符串是不可继承,字符串是一个常量是不可改变得。
10.4.1、创建字符串
当给String类型得变量赋值,虚拟机会创建一个字符串对象。
package com.api;
public class String1 {
public static void main(String[] args) {
//给字符串变量赋值时,虚拟机会根据值创建一个字符串对象
String str = "字符串";
//创建字符串对象
String str1 = new String("字符串1");
//字符串品拼接也会创建一个字符串对象
String str2 = str + str1;
System.out.println(str2);
}
}
运行结果
字符串1
10.4.2、字符串格式化
如果字符串不格式化就需要进行哦拼接,一旦变量多就会变得繁琐,所以我们可以使用字符串格式化来完成这项操作。
%s表示字符串,%d表示数字,%n表示换行
package com.api;
public class String1 {
public static void main(String[] args) {
String name ="张三";
int age = 20;
String form = "我叫%s,今年%d岁";
System.out.println(String.format(form, name,age));
}
}
运行结果
我叫张三,今年20岁
10.4.3、操作字符串
package com.api;
public class czZfc {
public static void main(String[] args) {
//charAt(int index)获取指定位置的字符,下标从0开始
String str = "helloword";
System.out.println("截取指定位置得字符串为:"+str.charAt(4));
//toCharArray() 将字符串转换成数组
char[] charArray = str.toCharArray();
for (int i = 0; i < charArray.length; i++) {
System.out.print(charArray[i]+"\t");
}
System.out.println();
//subStriing() 截取字符串
System.out.print("截取得字符串为:"+str.substring(0, 2));
System.out.println();
//分割字符串 split(以什么形式分割)
String str2 = "你好啊,世界,每天爱你多一点哦";
//以,得形式分割
String[] split = str2.split(",");
for (int i = 0; i < split.length; i++) {
System.out.println(split[i]);
}
//去掉空格 trim() 只去掉首位空格
String str3 = " gfhjsdgfsd ";
System.out.println(str3.trim());
//将字符转换成大写、小写
String str4 = "asfasfasf";
//转成大写
System.out.println(str4.toUpperCase());
//转成小写
System.out.println(str4.toLowerCase());
//查找字符串
//index Of() 字符串第一次出现得位置
//last indexOf()字符串最后一次出现得位置
//contains 是否包含子字符串
String str5 = "爱我中华!";
System.out.println("字符串第一次出现得位置是:"+str5.indexOf("我"));
System.out.println("字符串最后一次出现得位置是:"+str5.lastIndexOf("华"));
System.out.println("字符串是否被包含:"+str5.contains("a"));
//字符串替换
//replaceAll 替换所有的
//replaceFirst 只替换第一个
String str6 = "asbjaksfbhajskf";
//将所有得f替换成q
System.out.println(str6.replaceAll("f", "q"));
System.out.println(str6.replaceFirst(",",""));
}
}
运行结果
截取指定位置得字符串为:o
h e l l o w o r d
截取得字符串为:he
你好啊
世界
每天爱你多一点哦
gfhjsdgfsd
ASFASFASF
asfasfasf
字符串第一次出现得位置是:1
字符串最后一次出现得位置是:3
字符串是否被包含:false
asbjaksqbhajskq
asbjaksfbhajskf
10.4.4、字符串比较
package com.api;
public class bijiao {
public static void main(String[] args) {
//==比较字符串
String str1 = "abc";
String str2 = new String("abc");
//结果为false是因为==比较得是内存地址
System.out.println(str1==str2);
String str3 = "zxc";
String str4 = "zxc";
//结果为true是因为 字符串在赋值得时候会创建一个String对象
//当创建第二个对象得时候发现该字符串对象存在可以拿来直接使用,所以不会创建新得String对象
System.out.println(str3==str4);
//equals比较内容是否相同
System.out.println(str3.equals(str4));
//判断字符串以什么开头,以什么结尾
String str6 = "abcd";
System.out.println(str6.startsWith("a"));
System.out.println(str6.endsWith("d"));
}
}
运行结果
false
true
true
true
true
10.5、StringBuffer
java.lang.StringBuffer
因为String(字符串)是不可变得,所以我们要使用StringBuffer处理字符串,StringBuffrer()是可变字符串可以随意增删改查,并且容量会自动扩大。
package com.api;
public class StringBuffers {
public static void main(String[] args) {
String str = "";
StringBuffer sBuffer = new StringBuffer(str);
//append()追加字符串
sBuffer.append("你好啊,世界!");
System.out.println(sBuffer);
//删除初始位置到指定位置的字符串
sBuffer.delete(0, 2);
System.out.println(sBuffer);
//删除指定位置的字符串
sBuffer.deleteCharAt(1);
System.out.println(sBuffer);
//在指定的位置插入字符串
sBuffer.insert(4, "你好啊");
System.out.println(sBuffer);
//字符串反转
sBuffer.reverse();
System.out.println(sBuffer);
}
}
运行结果
你好啊,世界!
啊,世界!
啊世界!
啊世界!你好啊
啊好你!界世啊
10.6、StringBuffer和StringBuilder的区别
StringBuilder 类是 JDK 1.5 新增的类,功能和StringBuffer差不多,不同的是StringBuilder没有实现线程安全,所以是线程不安全的,如果要创建可变字符串优先使用StringBuffer,速度方面因为StringBuilder去掉了保证线程安全的那部分,减少了开销,所以比SttingBuffer快一些,但是不是绝对的。
在使用方面
操作少量的数据使用 String。
单线程操作大量数据使用 StringBuilder。
多线程操作大量数据使用 StringBuffer。
11、日期对象
11.1Date
java.util.Date;
所有的数据在计算机最后逗得以数字形式表示出来,日期也不例外,零这个数字,就代表Java中的时间原点,其对应的日期是1970年1月1日 8点0分0秒 。 (为什么是8点,因为中国的太平洋时区是UTC-8,刚好和格林威治时间差8个小时),因为1969年发布了第一个 UNIX 版本:AT&T,综合考虑,当时就把1970年当做了时间原点,所有的日期,都是以为这个0点为基准,每过一毫秒,就+1。
创建日期对象
package com.api;
import java.util.Date;
public class dates {
public static void main(String[] args) {
//创建日期对象
Date date = new Date();
System.out.println(date);
// // 从1970年1月1日 早上8点0分0秒 开始经历的毫秒数
Date date2 = new Date(10000);
System.out.println("从1970年1月1日 早上8点0分0秒 开始经历了10秒时间");
//get time以long型整数得到当前时间
System.out.println(date.getTime());
//和gettime一样得到当前日期的毫秒数
System.out.println(System.currentTimeMillis());
}
}
运行结果
Thu Aug 27 09:06:06 CST 2020
从1970年1月1日 早上8点0分0秒 开始经历了10秒时间
1598490366725
1598490366753
日期格式化
通过 SimpleDateFormat 将日期格式化。
package com.api;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.SimpleFormatter;
public class sim {
public static void main(String[] args) throws ParseException {
//y 代表年
//M 代表月
//d 代表日
//H 代表24进制的小时
//h 代表12进制的小时
//m 代表分钟
//s 代表秒
//S 代表毫秒
//创建日期格式化类,根据构造方法填入相对应的值
SimpleDateFormat sim = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
//创建日期对象
Date date = new Date();
//通过format方法将当前日期以字符串的形式进行输出
System.out.println(sim.format(date));
String str = "2020年08月27日 17时07分30秒";
Date parse = sim.parse(str);
System.out.println(parse.toString());
}
}
运行结果
2020年08月27日 09时18分23秒
Thu Aug 27 17:07:30 CST 2020
11.2、Calendar(日历对象)
Calendar常用于对日历的操作。
创建Calendar对象获取当前时间
package com.api;
import java.util.Calendar;
import java.util.Date;
public class calendar {
public static void main(String[] args) {
//通过单例模获取当前对象
Calendar cl = Calendar.getInstance();
System.out.println(cl);
}
}
运行结果
java.util.GregorianCalendar[time=1598491418827,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=31,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2020,MONTH=7,WEEK_OF_YEAR=35,WEEK_OF_MONTH=5,DAY_OF_MONTH=27,DAY_OF_YEAR=240,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=4,AM_PM=0,HOUR=9,HOUR_OF_DAY=9,MINUTE=23,SECOND=38,MILLISECOND=827,ZONE_OFFSET=28800000,DST_OFFSET=0]
11.2.1、操作Calendar对象
package com.api;
import java.util.Calendar;
import java.util.Date;
public class calendar {
public static void main(String[] args) {
//通过单例模获取当前对象
Calendar cl = Calendar.getInstance();
//获得当前时间
System.out.println(cl.getTime());
//获得当前年份
int year = cl.get(Calendar.YEAR);
System.out.println("当前年份是:"+year+"年");
//获得当前月份(月份从0开始所以要加1)
int month = cl.get(Calendar.MONTH)+1;
System.out.println("现在是:"+month+"月");
//获取日
int day = cl.get(Calendar.DATE);
System.out.println("现在是:"+day+"日");
//获取今天是星期几,以星期日为第一天所以要-一天
int week = cl.get(Calendar.DAY_OF_WEEK)-1;
System.out.println("今天是星期:"+week);
// 获取当前小时数(24 小时制)
int hour = cl.get(Calendar.HOUR_OF_DAY);
System.out.println(hour + "时");
System.out.println("星期" + week);
// 获取当前分钟
System.out.println(hour + "时");
int minute = cl.get(Calendar.MINUTE);
System.out.println(minute + "分");
// 获取当前秒数
int second = cl.get(Calendar.SECOND);
System.out.println(second + "秒");
// 获取毫秒数
int millisecond = cl.get(Calendar.MILLISECOND);
System.out.println(millisecond + "毫秒");
// 获取今天是本月第几天
int dayOfMonth = cl.get(Calendar.DAY_OF_MONTH);
System.out.println("今天是本月的第 " + dayOfMonth + " 天");
// 获取今天是本月第几周
int dayOfWeekInMonth = cl.get(Calendar.DAY_OF_WEEK_IN_MONTH);
System.out.println("今天是本月第 " + dayOfWeekInMonth + " 周");
// 获取今天是今年第几天
int many = cl.get(Calendar.DAY_OF_YEAR);
System.out.println("今天是今年第 " + many + " 天");
// 设置年月日,时分秒将默认采用当前值
cl.set(2012, 8, 8);
System.out.println("设置日期为 2012-8-8 后的时间:" + cl.getTime());
}
}
运行时间
Thu Aug 27 09:40:18 CST 2020
当前年份是:2020年
现在是:8月
现在是:27日
今天是星期:4
9时
星期4
9时
40分
18秒
611毫秒
今天是本月的第 27 天
今天是本月第 4 周
今天是今年第 240 天
设置日期为 2012-8-8 后的时间:Sat Sep 08 09:40:18 CST 2012
Calendar对象打印万年历
package com.api;
import java.util.Calendar;
import java.util.Scanner;
public class SRRLTest {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Calendar cal = Calendar.getInstance();
System.out.println("请输入年份:");
int year = sc.nextInt();
System.out.println("请输入月份:");
int month = sc.nextInt()-1;
cal.set(Calendar.YEAR,year);
cal.set(Calendar.MONTH,month);
System.out.println("日\t一\t二\t三\t四\t五\t六");
//得到这个月1号星期几
int dayofmonth = cal.get(Calendar.DAY_OF_MONTH);
cal.add(Calendar.DATE , - dayofmonth +1);
int xq = cal.get(Calendar.DAY_OF_WEEK);
//打空格
for (int i = 0; i
运行结果