类:类是一个模板,描述一类对象的行为和状态
对象:对象是类的一个实例,有状态和行为;比如说。一只狗,状态就是他有品种,名字,颜色等,行为
有摇尾巴,叫,吃等
方法:方法就是行为,一个类可以有很多方法,逻辑运算,数据
修改等都是在方法中完成的
实例变量:每个对象都有自己的实例变量,对象的状态就是由这些实例变量的值决定的
Java基本数据类型
变量是申请内存来储值,当创建变量的时候需要在内存中申请空间
根据变量的类型来为变量分配存储空间,只用来储存该类型数据
Java两大数据类型
内置数据类型和引用数据类型
内置数据类型
八种内置数据类型(六种数字数据类型,一种字符类型还有一种布尔类型)
不用记范围,直接打印输出 Inteager.size 这样就可以打印出范围
引用数据类型
引用数据类型类似于指针,引用类型指向一个对象,指向对象的变量就是引用变量。
这些变量在声明时被指定为一个特定的类型,一旦申明变量,类型就不能改变。
对象,数组都是引用数据类型
所有引用类型的默认值都是null
变量类型
类变量:独立与方法之外的变量,用ststic修饰
实例变量:独立与方法之外的变量,不用ststic修饰
局部变量:类的方法中的变量
Java 局部变量
局部变量声明在方法、构造方法或者语句块中;
局部变量在方法、构造方法、或者语句块被执行的时候创建,当它们执行完成后,变量将会被销毁;
访问修饰符不能用于局部变量;
局部变量只在声明它的方法、构造方法或者语句块中可见;
局部变量是在栈上分配的。
局部变量没有默认值,所以局部变量被声明后,必须经过初始化,才可以使用。
java修饰符
Java方法
方法定义的格式:
修饰符 返回值类型 方法名称 (参数类型 参数名称){
方法体
return 返回值;
}
解释:
修饰符:目前有固定写法。两个关键字 public static
返回值类型:方法最终的数据是什么类型
方法名称:自定义的名字,首字母小写,从第二个单词开始每个单词首字母大写
参数类型:进入方法的数据是什么类型
参数名称:进入方法的数据,对应的名称
方法体:需要执行的若干行代码
return :第一个作用一旦执行结束当前方法,第二带着后面的返回值交给调用处
返回值:方法的最终数据
注意事项:
返回值类型必须和返回值对应
如果参数多个,那么使用都用逗号分隔
如果不需要参数,那么小括号可以留空
定义一个没有返回值的方法
修饰符 void 方法名称 (参数类型 参数名称){
方法体
return ;//最后一行的return一般都是省略不写
}
注意事项
1.返回值没有不代表没有参数,参数和返回值没有必然联系
2.不能return一个具体的返回值
viod没有返回值
3.如果最后一行是“return”,那么可以不写,写与不写完全等效
4.没有返回值的方法,只能使用单独调用,不能使用打印调用或者赋值调用【重要】
返回值
只能有一个或者没有
demo 遍历数组
1.将数组中的元素逐一打印出来
2’定义一个数组
*返回值类型:只是打印显示而已,没有结果数据,所以用void
*方法名称:printArray
*参数列表:需要给我一个数组,我才能遍历它,所以需要一个int【】数组
3.调用方法:传入一个数组
有无返回值的对比
对比两种情况:
1.定义一个方法,用来【求出】数组元素的总和(告诉我最终的结果)
2.定义一个方法,用来【打印】数组元素的总和(自己打印就得了,不用告诉我结果)
结论:
需要计算的有返回值
只需要打印的就没有返回值
方法的重载(Overload )
方法重载:方法的名称相同,但是参数列表不同(Overload)
达到效果:对于类似功能的多个方法,只要记住一个相同的名字即可,可以根据参数列表的不同自动适配
注意事项:
1.参数个数不同
2.参数类型不同
3.参数的多类型的顺序不同(表达式当中需要运算的数据类型不一样,怎么办?谁的数据范围大,结果就是谁):比如先int后double,先double后int
重载与下列因素无关:
1.与返回值类型无关,无法根据返回值的不同进行重载;
2.与参数的名称无关,比如int a,int b和int x,int y;
参数传递
参数传递:在调用方法的时候,向方法内传入一些数据的动作
【形式参数】:在“定义”方法的时候,写在小括号之内的参数
例如:public static int sum(int a,int b){...}这里的a和b是在定义的时候写的,所以就是形式参数
【实际参数】;在“调用”方法的时候,真正传入方法里的数据,叫做实际参数
例如:int num=sum(10,20),这里的10和20是在调用方法的时候传入方法的,所以他们是实际参数
参数传递的过程中,有两项规则
1.对于基本数据类型(以及String)来说,形式参数的操作不会影响实际参数
2.对于引用数据类型(除了String)来说,形式参数的操作会影响到实际参数
类的定义
类是用来模仿现实事物的代码手段,事物分为属性,行为两个部分,类中也对应的包含了两个部分
1.成员变量(属性):将变量位置直接定义在类中,在方法外即为成员变量
2.成员方法(行为):将普通的方法去掉stataic关键字,即为成员方法
两个对象内存图
一个对象
对比局部变量和成员变量的不同
1.定义的位置不同【重点记忆】
局部变量:定义在方法内部
成员变量:直接定义在类中,在方法外面的
2.内存中的位置不一样
局部变量:在栈内存中,stack
成员变量:在堆内存中,heap
3.生命周期不一样
局部变量:随着方法的进栈而出现,随着方法的出栈而消失
成员变量:随着对象被创建而出现,随着对象被JVM回收而消失
4.默认值不一样【重点记忆】
局部变量:没有默认值,必须赋值之后才能使用
成员变量:如果没有赋值,那么会有一个默认值
private关键字
一旦使用了private关键字对成员进行了修饰,那么超出了本类范围之外,就不能访问了
如果需要使用private修饰的成员变量,可以使用“间接访问”
为private成员变量编写一对儿Setter Getter方法
例如:
在最前方加上一个private
专门定义了一个成员方法用来设置成员变量的数据,Setter方法
public void setAge (int num){
age = num;
}
专门定义了一个方法用来获取成员变量的数据,Getter方法
public void getAge(){
return age;
}
this关键字
当局部变量与和成员变量重名的时候,方法中会根据“就近原则”使用局部变量
如果希望区分一下
this.成员变量名
this关键字的静电作用:将重名的成员变量和局部变量区分开
扩展:
this关键字其实代表的是“当前对象”:通过谁调用了方法,谁就是this
构造方法:
专门用来创建对象的方法,当通过new关键字创建对象时,其实就是在调用构造方法
格式:
public 构造方法名 (参数类型 参数名称){
方法体
return //通常最后一行return省略不写
注意:
1.构造方法不能写放回值类型,连void都不能写
2.构造方法的名称必须和所在的类名完全一样,连大小写也要一样
}
3.构造方法的调用格式就是创建对象的格式
构造方法重载的好处:
定义一个无参数的构造方法,可以直接new对象
定义一个重载的全参数的构造方法,可以在new对象的同时方便对成员变量进行赋值
注意事项:
1.构造方法根本不写返回值类型,连void都不写
2.构造方法的名称和所在类名称必须完全相同,连大小写都要一样
3.构造方法也是可以进行承载的
4.构造方法如果没有自定义,那么将会默认赠送一个,如果自定义了至少一个,那么就不再赠送默认的
如何定义一个标准的类:
1.所有的成员变量都需要使用private关键字私有化
2.为每一个成员变量编写一对Getter Setter 方法
3.编写一个无参数的构造方法
4.编写一个全参数的构造方法
布尔类型的boolean值,那么setXxx规则不变,而getXxx余姚写成isXxx的形式
private boolean male;
public void setMale(boolean male){
this.male = male;
}
public boolean isMale (){
return male;
}
字符串的两个问题
1.对象肯定有一个类与之对应,那么字符串对应的类是谁,String
为什么String这个类,不需要导包就可以直接用?
所有的类都需要导包才能使用,除了两种情况
a. 要使用的目标类,和当前类位于同一个包下
b.要使用的目标类,位于java.lang包下,但是不包含子包内容
2.既然字符串是对象,那么为什么直接打印出来就是内容呢?
打印println方法 逻辑:
1.如果是字符串类型,那么就直接显示内容
2. 如果不是字符串类型,那么就想办法内部转换成字符串,然后再显示
一般的对象都是使用“类型信息+@+地址值”作为字符串内容的
字符串池
字符串是最为常用的对象,所以在程序设计中往往会出现很多个重复的字符串
为了节省内存,所以引入了“字符串池”的设计,可以重复利用字符串
关于字符串池的几点描述
1.字符串池是位于堆内存中的一小块空间,用来保存若干个字符串的地址值
2.字符串池当中绝对不会重复的字符串对应的地址,保证字符串不重复
3.凡是直接双引号的字符串默认都在池中,而new出来的字符串默认不在池中
对于基本类型来说,==是进行数据内容的相同比较,但是对于引用类型来说,==是进行地址值的相同比较
如果是两个对象,那么地址值必然不同,如果地址值相同,那么必然是同一个对象
字符串的内容不可变
字符串对象在内存中一旦被创建,那么内容不可以改变
字符串的内容不会发生改变,每当你觉得昊想是变了的时候,一定是创建了新的字符串
字符串的比较方法
如果使用 == 进行比较,那么是进行地址值的相同判断
如果希望进行字符串的内容比较,则需要使用String当中的成员方法
public boolean equals (object obj); 进行字符串的内容比较,严格区分大小写。参数obj就是另一个对象(跟谁比 )。object也是一种类型,可以接受任何类型的数据
public boolean equalsIgnoreCase(String str);进行字符串的内容比较,但是忽略大小写
注意事项:
1.要想进行字符串的内容比较,一定要使用equals方法,你要使用==运算
2.equals方法具有对称性,a.equals(b)和b.equals(a)效果一样
3. 小技巧,如果equals方法需要比较的两个字符串当中,有一个是常量,那么尽量将常量写在前面
4.直接写上的双引号就是字符串对象,所以用双引号直接点儿也能调用方法。
字符串的替换方法(敏感词过滤)
如果希望将字符串当中指定的部分进行替换操作,需要使用
public String replace (CharSequence olderStr,CharSequence newStr);将字符串当中所有出现的older部分,替换成为newOlder部分
参数olderStr代表需要替换的老字符串部分
参数newStr代表需要替换成为的新字符串部分
参数类型CharSequence现阶段可以简单地认为就是字符串String
字符串切割方法
使用方法
public String[] split(String regex);将regex作为标记进行切刀,返回切分之后的若干段字符串(字符串数组)
注意事项:
现阶段强烈推荐不要使用英文句点作为分割的标记
因为英文句点在正则表达式中有特殊含义
如果一定要使用英文句点,切割的标记应该使用“//.”(现阶段的固定写法)
而参数regex其实就是一个正则表达式
集合
集合和已经学过的数组比较类似,本身也是一种引用类型。也可以存放很多个数据
区别在于数组的长度不可以改变,集合的长度可以任意改变
集合包含很多种,ArrayList,HashSet,LinkedList,HashMap......
现阶段我们只学习最为简单的ArrayList一种即可,其他的集合类似
使用:
java.util.ArrayList是一个类,使用三步,导包,创建,使用
1.导包
import java.util.ArrayList
2.创建
类名称 对象名 = new 类名称();
ArrayList<泛型> Array = new ArrayList<>();
泛型,也就是集合当中存放的都是同意类型的数据
注意:泛型只能是引用类型,不能是基本类型
3.使用 :
如何在集合中存储基本数据类型
基本类型 对应的包装类
byte Byte
short Short
int Integer 【特殊】
long Long
float Float
double Double
char Character 【特殊】
boolean Boolean
从jdk1.5开始,基本数据类型可以和对应的包装类进行自动装箱拆箱
装箱:基本类型-->包装类
拆箱:包装类 -->基本类型
如何在集合中储存自定义数据类型
io流:
I:input,输入
o:output,输出
流:数据流
FileWriter 写文件
1.导包:
import java.io.FileWhiter;
2.创建,构造方法
public FileWriter(String fileName); 参数字符就是文件的路径名称
FileWriter fw = new FileWrite(“file01.txt”);
文件扩展名只能决定默认用什么软件打开软件,不能决定其内容
3.使用:成员方法
写数据:public void write (String str);参数就是需要写到文件中的字符串
关闭流:public void close();关闭释放相关资源
总结:
FileWriter基本使用步骤:创,写,关
注意事项:
1.千万不要忘记最后调用close方法进行关闭
2.创建的时候,如果提示可能有异常,那么就点击add throws...即可
FileWriter写数据的覆盖与追加
在使用FileWriter的时候:
1.如果指定的文件不存在,那么会自动创建该文件
2.如果指定的文件已经存在,那么将会覆盖写入
3.如果必须希望进行覆盖写入,而是希望追加,那么要用另外一种重载形式的构造方法
public FileWriter (String fileName , boolean append);第二个参数为true值,那么将会追加写入
文本文字就是数字
计算机当中一切都是数字,文本文件当中保存的就是数字
能够看到文字图形,是因为软件帮我们进行了翻译,翻译的规则就是:
ASCii码表,还有另外一张更大的表叫做Unicode码表
后者包含了全世界所有数以万计的文字
FileWriter提供了一种重载形式的write方法,可以直接根据数字写文件
public void write(int ch);参数就是单个文字所对应的数字值
FileWriter的重载形式
FileReader读数据的一般步骤
用来将文本文件中的字符读取到程序当中
1.导包
import java.io.FileReader;
2.创建
public FileReader(String fileName);参数任然是文件的路径名
FileReader fr = new FileReader("fileXxx.txt");
如果指定的文件名不存在,那么会直接报错
3.使用
读取单个字符:public int read();读取下一个字符,得到对应的ASCII或者Unicode值
关闭流,释放资源:public void close;
三个步骤:创,读,关;
如何使用FileReader读取字符数组
为了提高效率。FileReafer提供了另外一种重载形式的read方法
public int read(char[] buf);
参数是一个字符数组,用来承载读取到的多个字符
返回值代表的是数组中读取到的有效个数
BufferWriter的缓冲原理
BufferWriter和FileWriter差不多,也是一种用来写文件的类,属于字符输出类
区别与BufferWriter肚子里有一个长度为8192的char[]性字符数组,当作缓冲区使用
每次在写数据时,实际上都是在不断地向缓冲数组中添加字符
如果缓冲数组已经满了,那么将会统一的写入到硬盘中去
如果还未写满,那么就等待下一次的写入
如果最终关闭流的时候,数组任未满,那么也会将剩余的有效部分写到硬盘文件里
如何使用BufferedWriter?
1.首先创建一个普通的BufferedWriter
2.将这个普通的FileWriter包装成为缓冲的BufferedWriter,用构造方法
3.后面的BufferedWriter使用的方法和FileWriter基本一致
构造方法
public Buffered(FileWriter fw);参数就是一个普通的FileWriter对象
BufferedReader的缓冲原理
接口
接口的好处:通用性,隔离性
通用性:无论是医生还是警察还是司机
通用全都当作的学生对待
隔离性:无论是医生还是警察还是司机
特有的功能与我无关,我只关心学生相关的功能
接口的格式和组成部分
格式:
public interface 接口名称{
//
}
接口中的组成成分
1.抽象方法[学习重点]
2.常量
3.默认方法(java8)
4.静态方法(java8)
5.私有方法(java9)
接口中抽象方法定义
格式:
public abstract 返回值类型 方法名称(参数类型 参数名称);
注意:
1.接口中的抽象方法,修饰如果写必须是public abstract
2.接口中的抽象方法,修饰符可以省略不写。默认就是public abstract
3.抽象方法只有方法头,没有方法体大括号
接口实现类的定义
如果想要使用定义好的接口,必须有一个接口的实现类
定义实现类格式为:
public class 实现类的名称 implements 接口名称 {
//一定要覆盖写所有的抽象方法
}
注意:
什 么是覆盖重写Override 抽象方法
1.也就是将接口当中的抽象方法抄写过来
2.去掉abstract关键字
3.写上大括号方法体
package day09demo01;
public class Catimplements Animal{
public void eat (){
System.out.println("猫吃鱼");
};//吃东西
public void sleep (){
System.out.println("猫睡觉");
};//睡觉
}
Cat就是Animal接口的实现类,Cat类实现了Animal接口。
接口与实现类的基本使用
创建:
接口名称 引用名 = new 实现类名称();
调用:
引用名.抽象方法名(参数);
注意:
1.左面是接口类型,那么只能调用接口中定义好的内容,无法调用左侧实现类专有的方法
2.当调用接口当中的抽象方法时,真正进行运行的是右侧new的时候类的具体实现方法内容
3.总结记住一句话:调用的时候看左边,运行的时候看右边
面向接口编程
使用接口作为左侧类型的好处所在
屏蔽掉了右侧的个性特有的内容,达到隔离,统一的目的。
面向接口编程:
如果使用的功能,接口已经可以满足,那么就不在乎具体的类是谁,只在乎接口即可
Lambda表达式:(a,b)-> a + b
method方法需要一个Calaulator接口类型的参数
Lambda表达式就是充当了Calculator接口类型的参数
初步理解:
1.Lambda表达式前面的小括号,其实就是接口抽象方法的小括号
2.箭头代表拿着小括号的数据做什么事情,是一个指向的动作
3.箭头后面就代表这拿到了参数之后做什么事
Lambda表达式的语义本身就是代表了怎么做这件事情,没有对象概念在里面。
函数式接口
Java中使用Lambda表达式的前提是,必须有“函数式接口”
概念:有且仅有一个抽象方法的接口,叫做函数式接口
如何才能万无一失地检测一下当前的接口是不是函数式接口呢?
用一个固定的格式写在public interface前一行即可
@FunctionalInterface
public interface 函数式接口名 {
// ...
}
Lambda的标准格式
Lambda表达式要想使用,一定要有函数式接口的推断环境
1.要么通过方法的参数类型来确定是哪个函数式接口
要么通过赋值操作来确定哪个是函数式接口
Lambda的格式就是为了将抽象方法,翻译成一下三点
1.一些参数(方法参数)
2.一个箭头
3.一些代码(方法体)
例如抽象方法
public abstract int sum(int a,int b);
翻译成为Lambda的标准格式
(int a,int b) -> {return a + b; }
Lambda表达式上下文推断
调用方法的时候,参数类型是函数式接口,所以Lambda可以推断出来是哪个接口
也可以根据赋值语句左侧的类型来进行Lambda上下文推断
Lambda的简便格式
1.在Lambda表达式当中凡是可以推导的,都是可以省略的
2.如果参数有且仅有一个,那么小括号可以省略
3.如果语句只有一个,那么大括号和return也可以省略
前面学习的代码实现案例分析
1.创建一个集合用来存储5个英雄
创建一个Hero类,代表英雄
把集合内的对象换成hero对象
2.读文件,吧数据加到集合当中
3.判断一下集合中有没有内容,是不是新的
如果是新的队伍,没有人,就需要创建五个对象加入到集合中
如果不是新的队伍,已经有人了,就不需要创建了
遍历集合,输出其中的每一个对象的具体信息//循环5次进行遍历//统计一下综合战斗力是多少
判断一下集合是不是新的
if (isNew){
System.out.println("将集合重的数写到文件中”);
}
//如果不是新的,就什么也不用做
System.out.println("退出游戏")
方法引用(java 8)
Stream流(java 8)
模块化(java 9)
定义方法时,
有static的方法叫做静态方法
没有static的方法,叫做成员方法(实例方法)
定义静态方法的格式:
public static 返回值类型 方法名称(参数类型 参数名称){
//方法体
}
定义成员方法的格式:
public 返回值类型 方法名称(参数类型 参数名称){
//方法体
}
调用静态方法的格式
方法名(参数值);//直接调用本类中的静态方法,本类中的静态方法,也可以通过类名称调用
类名称.方法名(参数值);//调用另外一个类中的静态方法
调用成员方法的格式:
类名称 对象名 = new 类名称(); //首先创建对象
对象名.成员方法名(参数值); //通过对象名调用成员方法
同一类中直接调用:方法名(参数值);
再另外一个类中调用:类名称.方法名(参数值);
成员方法调用
没有static ,这是一个成员方法(实例方法,Instance Method)
需要调用成员方法就必须借助对象。
注意:
如果不创建对象,那么通过类名称只能调用静态方法。
如果创建了对象,那么通过对象名可以调用成员方法
通过对象名也可以调用静态方法,然而不推荐这么做
Lambda表达式冗余场景
在某些场景之下,Lambda表达式要做的事情,其实在另外一个地方已经写过了
那么此时如果通过Lambda表达式重复编写相同的代码,就是浪费。
方法引用的更优写法
在写Lambda表达式的地方写
方法引用:
如果Lambda表达式需要做的事情,在另一个类当中已经做过了,那么就可以直接拿过来进行替换Lambda
方法引用的写法:
通过类名称引用静态方法的格式:
类名::静态方法名
方法引用的另一个方法,通过对象引用成员方法格式:
对象名::成员方法名
Stream流的更优写法
day10Code
Stream流式思想
获取Stream流的常用方法
java 8 当中的“流“其实就是Stream接口的对象
JDK提供了一个流接口,java.util.stream.Stream
如何获取流?
1.根据集合获取流:集合名称.stream();
2.根据数组获取流 :Stream.of(数组名称);
Stream流的map映射方法:
获取流之后,可以使用映射方法:map(用于转换的Lambda表达式)
映射:就是将一个对象转换成另一个对象,把老对象映射到新对象上
Stream流的filter过滤方法:
如果希望对流中的元素进行过滤,可以使用过滤方法
filter(能产生boolean结果的Lambda),如果参数Lambda产生了true,则要元素;如果产生了false,则不要元素
Stream流的forEach方法:
如果希望再流中进行元素的遍历操作,可以使用forEach方法
forEach(Lambda表达式),意思是,对流当中的每一个元素都要进行操作
参数Lambda表达式必须是一个能够消费一个参数,而且不产生数据结果的Lambda
例如:
Lambda: s -> System.out.println(s);
方法引用: System::println
并发的Stream流
流当中的元素如果特别多,那么只有一个人在逐一,挨个儿处理,肯定比较慢,费劲
如果对流当中的元素,使用多个人同时并发处理,这就是并发
注意事项:
1.使用并发流的时候,到底有几个人进行同时操作呢?不用管,JDK自己处理
2.只要正确使用,就不会出现多个人抢到同一个元素的问题
3.如果已经获取了一个普通流,那么只要再调用一下parallel()方法也会变成并发流
总结:
1.直接获取并发流:.parallelStream()
2.已经获取了普通流,然后升级成为并发流:.stream().parallel()