变量
定义:在程序运行过程中,可以改变的量叫变量
语法格式:
数据类型 变量的名字 = 初始化的值;
数据类型:用来约束当前变量的类型的
变量的名字:就是自己起的名字。可以随便起吗?不可以
=:赋值号
初始化的值:第一次赋的值
数据类型
整型(4个):整数 byte short int long
浮点(2个):小数 float double
字符(1个):char
布尔(1个):
变量名字的命名规则
类的命名:
1.首字母大写
2.采用大驼峰的命名规则 由两个单词组成的,这两个单词的首字母都大写 HelloWorld
变量的命名:
1.变量首字母小写
2.变量可以使用字母,数字,下划线命名,但是不能以数字开头
3.采用的是小驼峰的命名规则【如果变量的名字是两个单词拼接起来的,首个单词小写,另外一个单词首字母大写】
4.命名 的时候一定要见名知意,看见英文意思就知道当前变量是什么意思了
5.已经被java或者系统所占用的关键字,咱们是不能起变量名字
转义字符
目的:把一个有特殊意义的字符转为无意义的字符或者把一个无意义的字符转为有特殊意义的字符
语法格式:\需要转义的字符
几个特殊的符号:\n:回车换行 \t:制表符 空格
运算符
算术运算符
数学中的 + - * / (整除) %(取余),先乘除后加减,先算小括号里面的,然后再算小括号外面面的,原则是从左向右进行执行
关系运算符
(是否大于) <(是否小于) >=(是否大于等于) <=(是否小于等于) !=(是否不等于) == (是否等于)
关系运算符的返回的结果必须是一个布尔类型的数据
逻辑运算符
与: &&
语法格式: 条件1 && 条件2 && …
条件的返回值必须是布尔类型的数据
条件1和条件2都为true的时候整体的结果返回的是true。条件1和条件2只要一个为false就整体false
银行里面的保险柜钥匙和密码
或:||
语法格式: 条件1 || 条件2 || …
条件的返回值必须是布尔类型的数据
条件1和条件2都为false的时候才为false,只要一个为true就为true
宿舍里面的钥匙:你拿一把,亲室友拿一把。 你的丢了。你室友可以开。除非两个都丢了
非: !
语法格式:!条件
取反
逻辑运算符的断路原则
逻辑与的断路原则:
条件1 && 条件2&&条件3…
如果条件1为false的话,整体就为false。那么条件2和条件3就不执行了
逻辑或的断路原则:
条件1 || 条件2||条件3…
如果条件为true的话,整体就为true。那么后面的条件就不再执行了
分支结构
if 分支
语法格式:
if (条件) {
语句体
}
条件的返回值必须是布尔类型的数据
执行流程:如果条件为true,就会执行大括号里面的语句体。如果条件为false,跳过大括号去执行下面的代码
if-else 分支
语法格式:
if (条件) {
语句体1
} else {
语句体2
}
执行流程:如果条件为true的话吗,执行语句体1跳过else后面大括号的语句体2 ,往下执行。
如果条件为false的话,跳过语句体1去执行语句体2。二者只选择其一
if-else if()分支
语法格式
if (条件1) {
语句体1
} else if (条件2) {
语句体2
} else if (条件3) {
语句体3
} else {
语句体
}
执行流程:如果条件1位true 执行语句体1,其他不执行。,一定要注意一句话。只要遇到条件为true就执行当前条件后面的与语句体。
跳过后面的额语句,执行非if-else语句
switch-case 分支
switch (表达式) {
case 常量1:
语句体1;
break;
case 常量2:
语句体2;
break;
case 常量3:
语句体3;
break;
…
default:
语句体n;
break;
}
执行流程:switch后面有个小括号,小括号里面是表达式,会产生一个值,这个值会和下面的case常量做匹配。如果匹配到就执行当前的语句体
循环结构
while循环
语法格式:
while (条件) {
语句体
}
执行流程:代码执行到while以后,首先判断while后面小括号里面的那个条件,如果条件为true 执行大括号里面的语句体。再次回到while关
键字,再次判断小括号里面的条件,如果条件为true执行语句体再次回到while 关键字,再次判断小括号里面的条件,如果为true就再次执行
如果为false 就结束循环
do-while 循环
语法格式:
do {
语句体
}while (条件);
执行流程:代码先找do关键字 就会执行大括号里面的语句体。然后才去判断while后面的条件,条件如果为true的话,回到do 再次执行语句体。再次判断条件…循环下去,直到条件为false,循环就结束了
while和do-while区别
while循环先判断条件是否成立,条件不成立,就不执行语句体
do-while 先执行语句体,然后再判断条件是否成立
for循环
语法格式:
for (表达式1;表达式2; 表达式3) {
语句体
}
执行流程:先执行表达式1,再执行表达式2 返回的true或者false 如果true继续往下走,执行语句体,再回到表达式3.在执行表达式2 判断是否true false
嵌套循环(双重foe循环)
语法格式
for(表达式1; 表达式2; 表达式3) {
for (表达式1;表达式2;表达式3) {
}
}
三目运算符
语法格式:
表达式 ? 表达式1 : 表达式2;
先判断?前面的表达式,如果表达式为true。执行表达式1。如果表达式为false,执行表达式2.
方法
无参数无返回值的方法
语法格式
public static void 方法名字 () {}
注意事项:
1.方法的声明必须放在main主函数的外部
2.在main主函数中调用自己定义好的方法
3.调用的时候需要方法的名字+小括号即可,用分号结尾即可
4.方法的名字的和变量的命名一样的
5.方法是条狗哪里需要哪里吼 方法声明完以后不执行,要在主函数中调用才执行.
有参数无返回值的方法
语法格式:
public static void 方法名字(数据类型 参数名字, 数据类型 参数名字,…) {}
注意事项:
1.声明的时候,方法有参数,这个参数叫形参
2.在方法的调用处,那个参数叫实参。实参和形参的数据类型必须保持一致
3.有几个形参就传入几个实参
无参数有返回值的方法
无参数有返回值的方法
语法格式:
public static 数据类型 方法名字() {
return 返回的值;//这个返回值必须和上面扥数据类型保持一致
}
return:关键字 返回的意思
【注意事项】
有返回值的方法在调用的时候一定要赋值给一个变量在main主函数中,拿到这个变量做下一步的操作
有参数有返回值的方法
语法格式:
public static 数据类型 方法名字 (数据类型 形参1, 数据类型 形参2,…){
return 返回的值;
}
break和continue的关键字
break
字面意思:终止和打断
public class Demo1 {
public static void main(String[] args) {
//看一下break关键字的
//i = 0 0< 10 true sout(0) break 终止循环
// for (int i = 0; i < 10; i++) {
// System.out.println(i);
// break;
// }
//打印1-100之间 数值,碰到50 往后就不再打印了
for (int i = 1; i < 101; i++) {
System.out.println(i);
if (i == 50) {
break;
}
}
}
}
continue
字面意思:继续,在循环里面,结束本次循环,进入下次循环
public class Demo2 {
public static void main(String[] args) {
/**
* i = 4 4 <10 true 4%5==0 false sout(4) i++
* i =5 5<10 true 5%5==0 true continue; 结束本次循环
*
* i++
* i = 6 6<10 true 6%5==0 fasle
*/
for (int i = 4; i < 10; i++) {
if (i % 5 == 0) {
//结束本次循环 进入到下一次循环
continue;
}
System.out.println(i);
}
}
}
数组
第一种声明方式:
数据类型[] 数组的名字 = new 数据类型[容量];
第二种声明方式:
数据类型[] 数组名字 = {值1, 值2, 值3 …}; 直接赋值,没有容量限制声明的时候直接进行赋值
第三种声明方式:
数据类型[] 数组的名字 = new 数据类型[]{值1, 值2,…};
注意事项:
int类型的数组 如果没有对当前索引下边进行赋值的时候,java会自动赋值 0
double类型的数组 如果没有对当前索引下边进行赋值的时候,java会自动赋值 0.0
char类型的数组 如果没有对当前索引下边进行赋值的时候,java会自动赋值 \ux0001 空的
String类型的数组 如果没有对当前索引下边进行赋值的时候,java会自动赋值 null
boolean类型的数组 如果没有对当前索引下边进行赋值的时候,java会自动赋值 false
数组内存分析图
数组的使用
public class Demo9 {
public static void main(String[] args) {
char[] chars = {'中', '国', '强', '大'};
for (int i = 0; i < chars.length; i++) {
System.out.println(chars[i]);
}
}
}
面向对象
面向对象的两个概念
类:是对一切相似事物的统称.是一个泛泛的概念。可以用来描述事物的特征和行为
对象:就是一个具体的实体。
类和对象的关系:对象是类的具体的实现,在类下面延伸出来具体对象,在java中先有类 再有对象
声明一个类的语法格式
public class 类名 {
对当前类属性(特征)的描述(变量)
对当前类行为的描述(方法)
}
创建类对象
类名 对象的名字 = new 类名();
Scanner scanner = new Scanner();
注意事项:创建对象的时候是main主函数中创建
可以使用对象的名字.属性 对属性进行吧赋值和取值
可以使用对象的名字.方法() 调用类中的方法
类和对象的内存分析
构造方法
无参数的构造
public 类名 () {
初始化的值;
}
1.必须写在声明的类里面,一般写在 属性的下面 方法 的上面
2.没有void关键字 也没有任何的 数据类型返回值
3.方法的名字必须是当前的类名
4.当实例化对象的时候,会调用当前类下面的无参数的构造方法
5.每一个类即使不写构造方法,会默认给你一个无参构造方法,所以直接new 类名()
有参的构造方法
public 类名 (参数) {
代码
}
注意事项:
1.如果在类中写了有参构造,本身默认的无参构造方法就没有了
2.new 类名()和 类名() 一一对应的关系
3.有参构造的目的是直接对属性进行赋值
关于有参构造和无参构造的注意事项
构造代码块
{
语句体
}
书写的位置:属性之后,构造方法之前
局部变量和成员变量
局部变量
public class Demo1 {
public static void main(String[] args) {
//有大括号的里面的变量可以称为局部变量
int number = 30;
if (3 < 4) {
//这个a就是成为你局部的变量
int a = 20;
}
//a = 30;
for (int i = 0; i < 10; i++) {
//i 和j 都是这for循环的局部变量 外部用不了
int j = 10;
System.out.println(i);
}
//System.out.println(j);
//System.out.println(num);
}
public static void test () {
//num 当前方法的局部变量
int num = 20;
}
}
总结:在同一个大括号下面可以使用当前变量,出了大括号就不能使用了
成员变量
在类中的属性叫成员变量,类下面的方法叫成员方法
public class Dog {
String name;//成员变量
//成员变量在类中任意的部位都可以使用
//成员方法
public void test () {
int age = 20;//这个是局部变量
System.out.println(name);
}
public void xixi () {
//age = 30;
name = "嘻嘻";
}
}
局部变量和成员变量的区别
封装
java 有三大特性:封装 继承 多态
封装属性的步骤:
1.使用private关键字 修饰属性
2.创建成员变量所对应的set方法和get方法
set方法:没有返回值,有参数。带参数目的为了在调用的时候进行赋值
get方法:有返回值,没有参数。只是获取通过set方法赋值的那个值
this关键字
这个的意思
1.使用this可以表示当前类对象
可以使用this关键字调用属性和方法
只能写在{}里面写this关键字
总结:以后只要碰到this关键字的话,就默认当成一个当前的对象看待
2.this关键字还可以调用构造方法【了解】
1.只能在构造方法中调用另外一个构造方法
2.不能在成员方法中调用构造方法this()
3.this关键字在调用构造方法的时候 只能写在首行
4.不能自己调用自己的构造方法
匿名对象
Person person = new Person();//person就是对象的名字
new Person();//匿名的对象
语法格式:
创建对象:
平常正常创建
类名 对象名字 = new 类名();
等号左边:对象的引用,在栈区定义的一个变量而已。
等号右边:在堆区创建了类对象,可以进行赋值
匿名对象创建的格式:
new 类名(); 等号左边没有。一次性的对象
继承
java 使用关键字:extends 进行继承的操作
语法格式:
class B extends A {
}
说明事项:
1.成员属性:
公开的成员属性(public)
子类可以使用父类的公开的成员属性
私有的成员属性(private)
子类是不能使用父类的私有化的成员属性
2.成员方法:
公开的成员方法(public)
子类可以使用父类的公开的成员方法
私有的成员方法(private)
子类可以不能使用父类的私有的成员方法
3.构造方法
子类继承了父类,在实例化子类的时候,子类的无参数的构造执行。并且也会执行父类的无参构造方法。执行顺序,先父类的构造方法,再子类的构造方法。从这个可以看出来,尽管只new 了子类但是父类也会被实例化
java继承的内存分析图
super关键字
super代表当前子类对父类的引用;this可以表示当前类对象
1.可以作为父类的类对象
2.super可以调用父类的构造方法
【注意事项】:
1.想要使用super关键字必须写在子类中,所以必须得有继承关系
2.super在子类中调用父类的东西
重写
重写:当父类的需求满足不了子类的需求了,需要对父类的方法进行重写。
重写:
1.必须得有继承
2.父类的成员方法必须是公开的
3.重写的时候子类的方法必须和父类一模一样(返回值,参数,方法的名字)
4.必须在子类中重写父类的方法
重载
在java中,同一个类中多个方法可以有相同名字。但是参数列表不同。这就是方法的重载
【注意事项】:
1.方法的重载必须在同一类中
2.方法的名字必须一样
3.方法的参数必须不一样
4.返回值可以一样也可以不一样
5.同一个类中有参构造方法和无参的构造也叫方法的重载
面试题:简单描述一下方法的重载和重写
重写:
1.必须有继承关系
2.父类的成员方法必须是公开
3.子类的方法必须和父类的方法一致(返回值,方法名字 ,参数)
4.必须子类中去重写父类的方法
重载:
1.方法的重载必须在同一类中
2.方法的名字必须一样
3.方法的参数必须不一样
4.返回值可以一样也可以不一样
5.同一个类中有参构造方法和无参的构造也叫方法的重载
抽象类
使用关键字abstract修饰的类的叫抽象类
使用关键字abstract修饰的方法的叫抽象方法
1.在一个类中可以声明一个抽象的方法,抽象方法没有方法体(没有大括号),后面使用分号结束
2.如果一个类中有抽象方法,这个类必须是抽象类。有抽象方法必须是一个抽象类
3.抽象类不能被实例
4.抽象类下面可以有非抽象的方法
5.由于抽象类不能被实例化,咱们只能继承,然后使用这个类
6.在抽象类中,子类去继承抽象类,必须重写抽象方法,非抽象方法可以重写也可以不重写,不强制
7.一个抽象类去继承另外一个抽象类
final关键字
1.final修饰成员变量
使用final修饰的成员变量必须进行赋值(初始化),一旦被赋值,这个变量不可以改变
2.final修饰局部变量
修饰局部变量的时候,可以先不赋值,然后再赋值。一旦赋值以后就不能修改了。
3.final修饰成员方法
使用final修饰的成员方法,不能被重写
4.final修饰类
final修饰的类不能被继承
5.final修饰对象的引用
不能被别的对象进行赋值
接口
语法格式:
interface 接口的名字 {
成员属性;//用的不多
成员方法;//用的比较多
}
注意事项:
1.接口下面可以声明成员变量,但是默认是final和static修饰的
2.在接口下面的方法是抽象方法不带方法体的,但是有特例
3.这个特例是使用default修饰的一个方法可以带方法体
4.接口能被实例化吗?不能。但是想要使用这个接口的话,可以新建一个类,然后去实现(implements)这个接口即可
5.必须全部实现接口下面的抽象方法
6.一个类可以实现多个接口(相当于多继承)
7.一个抽象类能不能实现一个接口,可以的
8.一个接口可以继承(extends)另外一个接口
面试题:接口和抽象类的区别
默认方法实现:抽象类可以有默认的方法实现;接口不能有默认的方法实现。
实现:抽象类的子类使用 extends 来继承;接口必须使用 implements 来实现接口。
构造函数:抽象类可以有构造函数;接口不能有。
main 方法:抽象类可以有 main 方法,并且我们能运行它;接口不能有 main 方法。
实现数量:类可以实现很多个接口;但是只能继承一个抽象类。
访问修饰符:接口中的方法默认使用 public 修饰;抽象类中的方法可以是任意访问修饰符。
static关键字
1.static修饰成员变量
语法格式:static int age;//静态变量
【注意事项】:
1.使用static修饰成员变量的时候在调用静态的成员变量的时候
类名.静态的变量名 不需要借助于对象,早于对象的创建。和对象没有关系
2.代码中没有创建对象的时候,static修饰的变量已经被加载进来了。
3.分析内存:
只要是static修饰的变量,都在.class文件编译阶段就已经加载到内存的方法区了。
2.static 修饰成员方法
语法格式:
public static void/数据类型 方法名字(){
}
调用:
类名.方法()
【注意事项】:
1.静态的成员方法和对象无关,直接使用类名直接调用
2.静态的成员方法会随着.class文件的加载而加载,也会被加载到方法区。早于对象的创建的
3.静态方法不能被重写
4.静态方法中能不能使用非静态的成员属性和成员方法
静态的成员方法早于对象的创建,普通的成员属性和成员方法只能是对象创建好以后才能进行调用的
5.静态方法中能不能创建对象?能!!!
3.static修饰代码块【静态代码块】
语法格式:
static {
代码
}
类文件只要加载,静态代码块就会被加载
执行顺序 静态代码块-----》构造代码块----------》构造方法
面试题:为什么静态代码块优先于构造代码块和构造方法执行?
因为构造代码块和构造方法在实例化对象的时候才真正的执行
静态代码块和对象没有关系,是在.class被加载以后就立马执行的,早于对象的创建
异常
捕捉
语法格式:
try {
有可能出现的异常代码
} catch(Exception e) {
针对上面异常的处理方案
}
抛出
使用两个关键字:
throw:在方法中抛出异常对象。
throws:用在方法的声明的位置,告知调用者。当前抛出的异常有哪些。
String类方法
获取字符串长度 int length();
获取特定位置的字符 char charAt(int index);
获取特定字符的位置 int indexOf(char ch); int indexOf(String str);
获取指定字符最后一个的位置 int lastIndexOf(char ch);
字符串的拼接 concat();
返回值是布尔类型的方法
是否以指定的字符结束 boolean endsWith(String str);
判断一个字符串是否为空 boolean isEmpty();
是否包含指定的字符串 boolean contains(String str);
忽略大小写是否相等 boolean eaqualsIgnoreCase(String otherStrinf);
将字符数组转为字符串
String(char[] chs);
String(char[] chs, int offset, int count)
static String valueOf(char[] chs);
将字符串转为字符数组
char[] toCharArray();
字符串替换 String replace(char oldChar, char newChar);
String replaceAll(String old, String new);
切割字符串:String[] split(String regex);
截取字符串:String subString(int beginIndex);
String subString(int beginIndex, int endIndex); 要头不要尾
将小写字母转为大写字母:String toUpperCase();
将大写字母转为小写字母:String toLowerCase();
去除收尾空格的:String trim();
泛型
泛型的语法格式
权限修饰符 [static] <无意义的占位符> 返回值的类型 方法名字 (参数类型) {
}
public <T> void get(T t){}
自定义泛型在类中如何使用
class 类名<无意义的占位符> {
属性
方法(带有泛型的)
}
【注意事项】:
1.在泛型类中,成员方法不用带 因为一旦带了,这个方法约束的数据和当前类约束的就不一样了
2.在泛型类中,带有泛型的静态方法和类的泛型没有关系
自定义泛型在接口中如何使用
interface 接口名字<T> {
}
权限修饰符
集合
Collection接口
增:
boolean add(E e);添加指定的数据到指定的位置
boolean addAll(Collection<? extends E>);添加另外一个集合到当前集合对象中。
但是一定要保证两个集合的泛型保持一致
删除:
boolean remove(Object obj);删除指定的元素
boolean removeAll(Collection<? extends E>);删除两个集合中的交集
void clear();清空所有的元素
查:
int size();查看集合中元素的个数
Object[] toArray();将集合转为Object类型的数组 就意味着以后数组和集合可以互相转换
boolean contains(Object obj);判断一个元素是否在当前集合中
boolean isEmpty();判断集合元素是否为空。如果有数据就是一个false 没有数据就是一个true
迭代器
hasNext() 判断是否有下一个元素,有的话就是true 没有下一个元素就是一个false
iterator.next()//next方法做了两件事情:1.获取下一个元素的 2将指针往下挪一位
List接口
特点:有序的,可以重复的
COllection下面的方法,在List下面都有的,因为是继承关系的 子类可以使用父类的方法
增:
boolean add(int index, E e);在指定的位置添加指定的数据
boolean addAll(int index, Collection<? extends E> c);在指定的位置下面存入另外一个集合
删:
boolean remove(E e);删除指定的元素 和索引没有关系
E remove(int index); 通过索引删除指定的数据,并返回删除的数据 这个太强大了
改:
E set(int index, E element) 3 4 5 6
在指定位置替换指定的元素,并返回一个被替换的元素
查:
E get(int index);通过索引把指定的元素取出来
int indexOf(Object O);查找指定元素第一次下标,如果没有这个元素的话就返回-1
int lastIndexOf(Object o);查找指定元素的最后一次下标
List<E> subList(int startIndex, int endIndex); 从集合中通过索引截取一部分。这个索引是要头不要尾的
LinkedList
简单聊一下LinkedList
LinkedList 底层是双向链表,并且实现了一个接口队列(先进先出)Deque
查找慢:因为底层是采用的二分法查找的算法 时间复杂度是n/2 不是一下就找到的
增删快:直接找到要插入的前置节点和后置节点,来进行插入或删除,其他元素不用
和ArrayList刚好相反
Object类
Object下的equals是比较内存地址,String类下的是判断两个对象是否相等
Set
Set集合是无序的,不可重复的
匿名内部类
基于抽象类的匿名内部类
//定义一个抽象类
abstract class Animal{
public abstract void eat();
}
public class Demo1 {
public static void main(String[] args) {
//直接new抽象类的方法名
new Animal() {
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("在吃饭");
}
}.eat();//匿名对象.方法();
}
}
基于接口的匿名内部类
interface Pig {
public void eat();
}
//不用再单独写一个类去实现这个接口
public class Demo3 {
public static void main(String[] args) {
new Pig() {
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("猪吃主食");
}
}.eat();
}
}
匿名内部类语法格式:接口/父类类型 引用变量名 = new 接口/父类类型(){方法的重写};
java8新特新Lamda表达式 格式:(参数列表)-> {方法体}
Map集合
双边队列的
Map<K, V>
K:键 key 键是不能重复的,是唯一的
V:值 value 值可以重复的
Map集合下面常用的方法
增:
put(K key, V value);存放的是一个键值对的数据
putAll(Map<? extends K> k, Map<? extends V> v);将一个map集合存放到另外一个map集合中
删:
remove(Object k);通过键删除整个键值对,并返回被删除的值
改:
put(K key, V value); 当key存在的时候,就修改。当key不存在的时候,就添加
查:
int size();键值对有效的个数
boolean isEmpty();是否为空,map集合为空就返回true,不为空就返回false
boolean containsKey();是否包含这个键
boolean containsValue();是否包含这个值
Set <k> keySet()获取map集合中键,返回是set集合
返回值是一个Set集合为啥不是一个List集合,map集合中键 是无序的不可以重复
V get(Object k);通过键获取值
Collection<V> values();获取map集合中所有的value值,返回的是Collection集合
Set<Map.entry<K, V>>entrySet()`;将键值对实体成一个Set集合
File
相对路径:
相对一个参照物 我在隔壁,参照物是咱们教室
./当前工作目录
…/相对于本级目录,上一级目录
…/…/相对于本级目录的上两级目录
绝对路径:
从磁盘的根目录 一级一级的找
路径斜线问题:
1./ window和Linux系统都是可以的
2.\ windows系统可以 其他系统不支持
开发中一般使用/
File类构造方法和方法
使用File类创建文件或者文件夹
删除文件或者文件夹
File类几个判断方法
返回值是String类型的方法
返回值是long的一些方法
文件列表方法
IO流
I:
Input 输入流,从硬盘上面读取数据到内存里面,这叫输入
应用场景:磁盘上有一个1.TXT文件,可以将1.txt文件中的内容 读取到java代码中
O:
output 输出流, 从内存中写入到硬盘上面,这叫输出
应用场景:java 代码有一个String类型的数据,将整个String发类型的数据
字节输入流:
InputStream
直接的子类FileInputStream
FileInputStream不具备缓冲的效果,象要具备缓冲效果咋办
借助于一个叫BufferedInputStream 字节缓冲输入流
字节输出流:
OutputStream
直接子类FileOutpuStream 文件字节输出流
输出流是干嘛?内存-》磁盘
在java代码里面写一个字符串,写入到磁盘中某一个文件中
FileOutpuStream没有缓冲,如果想要加缓冲效果,需要加缓冲流
BufferedOutputStream 字节缓冲输入流
字节输入流
字符输入流:
Reader
有一个孙子类叫FileReader
专门处理文本类型的,一个非常方便的类,但是他处理音频视频图片是不行的,有可能出错
底层依旧是使用字节进行读取的,但是中间会进行解码操作变成字符,但是一旦解码失败。读取数据将会失败。所以以后开发中不用Reader,老老实实的使用字节输入流不要用字符流
int read()
读一个字符
int read(char[] cbuf, int off, int len)
将字符读入数组的一部分。
String readLine()
读一行文字。
字节输入流
字符输出流
Writer
有一个孙子类FileWriter
FileWriter不具备缓冲效果的,借助于BufferedWriter
从内存中写入到磁盘
StringBuffer类
线程安全,可变的字符序列。 字符串缓冲区就像一个String
但可以修改。 String类拼接是开辟另外一个内存 ,StringBuffer直接在缓冲区域的后面直接添加
StringBuilder(线程不安全的) 比StringBuffer(线程安全的)快 比String 快
开发中遇到的String类型的数据偏多吗,所以用String用的比较多
枚举类
//枚举类的语法格式 enum代替class
//枚举类只能写常量 常量大写
enum Color {
RED,GREEN, BLUE
}
public class Demo2 {
public static void main(String[] args) {
//使用枚举下面的常量
//枚举类.常量 获取当前的常量
Color c1 = Color.RED;
System.out.println(c1);
}
}
包装类
int====>Integer
byte===>Byte
short====>Short
long====>Long
float====>Float
double ===>Double
char===>Charater
boolean===>Boolean
除了int 和char 其他的包装了都是首字母大写
装箱:将基本数据类型转为包装类对象
拆箱:将包装类对象转为基本数据类型
***Value();将包装类对象转为基本数据类型的
Integer integer2 = new Integer(34);
int int2 = integer2.intValue();//返回值是int 类型的数据
System.out.println(int2);
Short short1 = new Short((short)45);
short short2 = short1.shortValue();
System.out.println(short2)
;
parse****();将字符串转为基本数据类型【重点开发要用!!!】
int v2 = Integer.parseInt("89");//开发要用 数字字符串
System.out.println(v2);//int类型的89
valueOf();将基本数据类型转为包装类【开发中也会用】
//一般如果怕精度丢失的的话,先用字符串来表示,然后再转为double
double d2 = Double.parseDouble("89.99999");
System.out.println(d2);
byte byte4 = 45;
Byte b4 = Byte.valueOf(byte4);//将 基本数据类型转为包装类
System.out.println(b4);
Math类
Math类是专门处理数学高级计算的类,Math全是静态方法,直接拿类名来调用的
public class Demo1 {
public static void main(String[] args) {
System.out.println(Math.abs(-9.8));//绝对值
System.out.println(Math.max(1, 2));//最大值
System.out.println(Math.min(3, 5));//最小值
//求三个及三个以上数的最大值
System.out.println(Math.max(Math.max(3, 4), 5));
//要百十个的话比较大小的话,就循环吧
//面试不会用咱们现在学的常用类的方法
System.out.println(Math.ceil(3.4));//向上取整 4.0
System.out.println(Math.floor(5.6));//向下取整 5.0
System.out.println(Math.round(4.5));//四舍五入 5
System.out.println(Math.random());//[0, 1) 包含0 不包含1的随机数
//random() 返回值是double类型的数据
//随机出来0~100直接的整数
System.out.println((int)(Math.random() * 100));
}
}
Random类
这个类是专门处理随机数的,提供了大量的随机数的方法
public class Demo1 {
public static void main(String[] args) {
Random random = new Random();
System.out.println(random);
System.out.println(random.nextBoolean());//随机生成一个布尔类型的数据
System.out.println(random.nextInt());//随机生成一个整型的数据
System.out.println(random.nextFloat());//
System.out.println(random.nextDouble());
//100种子 是啥意思?
Random random1 = new Random(100);
System.out.println(random1);
System.out.println(random1.nextInt());
}
}
System类
System类是系统类,提供了一静态的方法和静态的属性
public class Demo1 {
public static void main(String[] args) {
System.out.println("hello world");//正常颜色的字体
Scanner scanner = new Scanner(System.in);
System.err.println("heheda");//红色的字体
//获取当前时间 1641968933855 1970 1.1 0时0分-刚才代码执行时间之间的毫秒数
System.out.println(System.currentTimeMillis());
Properties properties = System.getProperties();
System.out.println(properties.get("os.name"));
System.out.println(properties.get("os.version"));
System.out.println(properties.get("user.name"));
System.out.println(properties.get("user.dir"));
System.out.println(properties.get("java.version"));
}
}
Runtime类
public class Demo1 {
public static void main(String[] args) throws IOException {
Runtime runtime = Runtime.getRuntime();
System.out.println(runtime.maxMemory()/1024/1024);// 1027866624 单位是字节Java虚拟机将尝试使用的最大内存量。
System.out.println(runtime.freeMemory()/1024/1024);//空闲内存
//在咱们电脑中打开一个软件,双击这个软件,还可以通过java代码来软件
runtime.exec("C:\\Program Files (x86)\\Notepad++\\notepad++.exe");
}
}
Date类
专门处理电脑日期的一个类
public class Demo1 {
public static void main(String[] args) {
Date date = new Date();
System.out.println(date);
System.out.println(date.getYear() + 1900);
System.out.println(date.getMonth() + 1);
System.out.println(date.getDay());//3代表星期几
System.out.println(date.getHours());//获取小时
}
}
Calendar类
public class Demo2 {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
//通过get方法获取系统默认的一个常量 Year
System.out.println(calendar.get(Calendar.YEAR));//年
System.out.println(calendar.get(Calendar.MONTH));//月 月份从1开始
System.out.println(calendar.get(Calendar.DAY_OF_MONTH));//获取当月的第几天
System.out.println(calendar.get(Calendar.DAY_OF_WEEK));
System.out.println(calendar.get(Calendar.DAY_OF_YEAR));
System.out.println(calendar.get(Calendar.HOUR));
System.out.println(calendar.get(Calendar.MINUTE));
System.out.println(calendar.get(Calendar.SECOND));
//获取当前时间
Date time = calendar.getTime();
System.out.println(time);
//Wed Jan 12 15:52:33 CST 2022 这个时间不太友好 对咱们中国人不太友好
//格式当前的时间吗,把它变成中国人能看懂的时间
//M 代表的是月份 m代表的是分钟 y代表年份 d代表的是一个月里面的第几天
//SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
System.out.println(sdf.format(time));
//2022-01-12 15:56:38 以后开发那就用这个
}
}
进程
进程是需要通过系统的分配,获取系统当前的CPU,内存,显卡,网络等这些资源
1.独立性
2.互斥性
线程
线程是组成进程的最小基本单位,每一个进程至少得有一个线程
1.抢占式运行 :CPU在执行的时候,是按照时间片进行执行的。单位的时间片是相互抢占的
2.资源共享性 :一个应用程序中的线程可以共享当前的资源。比如CPU,内存,网络
Java程序:
一个java程序就是一个进程 Demo1main主函数 属一个应用程序
一个java应用程序至少有两个线程:
1.main主函数线程 2.jvm 垃圾回收
进程和线程的区别【面试题】
进程是一个完整的程序
线程是进程里面的执行的一个功能。
一个应用程序是由多个线程组成的
进程申请是系统的资源
线程申请是进程的资源
多个线程在执行的时候,cpu会根据每个线程分配的时间片聊来随机抢占执行
每个线程最多占用的时间片大概是20ms,过了时间片,就切换到其他线程了
并发和并行
并发:同时发生,轮流交替执行
并行:真正意义上的同时执行
创建线程的两种方式
第一种创建方式
Thread类:
1.声明一个Thread的子类,重写run方法
2.调用start开启线程
class MyThread1 extends Thread {
@Override
public void run() {
//for循环
for (int i = 0; i < 100; i++) {
System.out.println("我是Mythread1线程里面的代码");
}
}
}
class MyThread2 extends Thread {
@Override
public void run() {
//for循环
for (int i = 0; i < 100; i++) {
System.out.println("我是Mythread2线程里面的代码");
}
}
}
public class Demo1 {
public static void main(String[] args) {
//main一个线程
//实例化出来一个线程对象
MyThread1 myThread1 = new MyThread1();
//通过调用start方法开启线程一定是start方法
myThread1.start();
MyThread2 myThread2 = new MyThread2();
myThread2.start();
//4个线程 2个myThread 1main 1jvm 垃圾回收器
for (int i = 0; i < 100; i++) {
System.out.println("我是main主函数线程");
}
}
}
第二种创建方式【开发中用的】
1.写一个类去实现Runnable接口,实现run方法
2.实例化Thread类,然后构造器的参数是一个实现Runnable接口的对象
class MyThread4 implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 100; i++) {
System.out.println("MyThread" + i);
}
}
}
public class Demo2 {
public static void main(String[] args) {
//第二种写法
Thread thread = new Thread(new MyThread4());
thread.start();//开启线程
for (int i = 0; i < 100; i++) {
System.out.println("main:" + i);
}
}
}
线程下面的方法
构造方法
成员方法:
static Thread currentThread();获取当前线程对象
String getName();获取当前线程名字的
void setName(String name);设置当前线程的名字
void setPriority(int newPriority);设置当前线程的优先级。这个优先级只会增加线程执行的概率但是真正的会不会优先不一定
int getPriority();获取当前线程优先级的
static void sleep();让线程休眠多少毫秒
在run方法中调用Thread.sleep();只能try-catch不能抛
锁
synchronised Java 的关键字 同步锁
咱们线程是不安全的,随机抢占的。能不能让其线程有规律的执行呢?
可以的就是加锁。一个线程抢到资源以后,加上锁以后,这个线程先执行结束,会自动的释放锁 其他线程会进行抢占
修饰代码块
一个线程访问一个对象中synchronised(this)同步代码块的时候,其他视图访问该对象的线程就会被阻塞
synchronised (this) {
代码块
}
class SynThread1 implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
//开始锁for循环 加上锁
/**
* 在同一时刻 线程会进到run方法中,发现有一个锁
* 假如SYN抢到了这个锁 syn 线程在锁的外面等待着
* SYN抢到了,就要把for循环代码执行完,锁会自动释放
* syn 才抢到,加锁了,也要把下面for循环执行完
*/
synchronized (Object.class) {
//加锁的这一部分,只会让一个线程先执行完。释放锁另外一个线程再进来
//this 不是线程1 也不是线程2
System.out.println(this.toString());
for (int i = 0; i < 5; i++) {
System.out.println("线程的名字:" +Thread.currentThread().getName() );
}
}
}
}
死锁
死锁是一个状态,当两个线程互相持有对方的需要的资源的时候,却不主动释放自己的资源的时候,大致大家都用不了,
线程就无法往下执行了。
开发中能用死锁?不能!!!代码走不去的
线程的生命周期
线程创建好以后,开启线程start 方法,可运行状态,运行状态,阻塞状态,消亡
创建开启线程: start()
可运行状态:线程在抢占在等待,如果抢到的话就接着往下执行,如果没有抢到就等待
运行状态:真正的执行线程下面run方法
阻塞状态:锁,sleep, wait
消亡状态:线程执行结束以后
线程的几个重要的方法
wait();
1.让线程进入到等待状态。
2.wait方法和锁一起使用。
3.需要通过对象调用。锁对象来调用
notify():
1.唤醒线程
2.方法和锁一起使用。
3.需要通过对象调用。锁对象来调用
反射
java的反射的意思是在运行期间可以动态的获取类的属性,方法,构造方法,父类,接口等内存的一种机制
反射的本质是反着来。之前通过new 一个类来获取类的信息(属性,方法,构造方法等)。
获取Class对象【.class】
java 能够将.java 文件编译成为.class文件,这个.class文件包含原来类的所有的信息
.class文件在运行过程中会被ClassLoader加载到虚拟机。当.class文件加载到虚拟机以后。
public class Demo1 {
public static void main(String[] args) throws ClassNotFoundException {
//不用反射的话,
//Person person = new Person();
//反射的一种写法
//要把字节码文件对象获取出来,
//Person.class所对应的Class对象获取出来
//第一种方式获取字节码文件对象
Class<?> aClass= Class.forName("com.qfedu.a_reflect.Person");
System.out.println(aClass);
//第二种方式
Class<Person> personClass = Person.class;
System.out.println(personClass);
//第三种方式
Class <? extends Person> aClass2 = new Person().getClass();
System.out.println(aClass2);
}
}
获取Constructor类对象
这个Constructor这类是反射所对应的构造方法的一个类对象
描述构造方法
Constructor[] getConstructors();
获取当前类下面的所有的非私有化的构造方法
Constructor[] getDeclaredConstructors();
获取当前类下面的所有的构造方法
Constructor getConstructor(Class ...parameterType);
获取一个非私有化的构造方法
Constructor getDeclaredConstructor(Class ...parameterType);
获取一个私有化的构造方法
以上的方法是Class调用的
下面这个方法Constructor对象调用的
Object newInstance();通过constructor对象创建出来一个对象
获取Field类对象
Field[] getFields();
获取public 修饰的属性
Field[] getDeclaredFields();
获取私有的属性
Filed getField(String name);
通过属性的名字获取属性对象
public class Demo5 {
public static void main(String[] args) throws Exception{
Class<?> aClass = Class.forName("com.qfedu.a_reflect.Person");
//获取属性对象 public 修饰的属性
Field[] fields = aClass.getFields();
// for (Field field : fields) {
// System.out.println(field);
// }
//获取所有的属性
Field[] fields2 = aClass.getDeclaredFields();
for (Field field : fields2) {
System.out.println(field);
}
Person person = (Person)aClass.getConstructor(null).newInstance(null);
//获取单个属性 传参是一个属性的名字
Field field = aClass.getField("sex");
//属性进行赋值,我得知道这个属性在哪个类下下面
field.set(person, true);
System.out.println(person);
//私有化的属性进行赋值
Field field2 = aClass.getDeclaredField("name");
//对name属性进行赋值
field2.setAccessible(true);//暴力反射
field2.set(person, "骚磊");
System.out.println(person);
}
}
Lambda表达式
interface Myinterface {
void doSomthing(String s);
}
public class Demo1 {
public static void main(String[] args) {
Myinterface a = (s)-> System.out.println(s);
a.doSomthing("heheda");
enact(s-> System.out.println(s), "hello world");
}
public static void enact(Myinterface myinterface, String s){
myinterface.doSomthing(s);
}
}