一:java的写法
1,能自己搭建java环境
2、能够编写hello Word程序
3、掌握环境变量path的原理,以及如何配置
4、掌握环境变量classpath的原理以及如何配置
* class path是给classloader类加载指路的
* classpath=自己写的java代码文件的路径
5、java的注释
6、public class和 class区别
* 一个java源文件中当中可以定义多个class
* 一个java原文件中public 的class不是必须的
* 一个class是会定义生成一个xxx.class字节码的文件
* 一个java源文件中定义公开的类的话,public的class只能有一个,而且该类的名称必须和java源文件名一致
* 每一个class都可以编写main方法,都可以设置程序的入口
* 想执行那个程序,就执行相应的方法
注意:当命令窗口执行java hello 那么要求hello.class必须有主方法
二: java的语言基础
1、java的方法的名规则习惯
1、标识符:
标识符可以标识什么元素
* 类名
* 方法名
* 变量名
* 接口名
* 常量名
高亮显示为黑色的为标识符
命令规则:
* 只能由数字,字母,下划线,美元符号,
* 且不能有数字开头
* 区分大小写
* 不能是关键字
命名规范:
* 最好知名之意
* 遵守驼峰命名规范
* 类名、接口名: 首字母大写,后面每个单词首字母大写 AdminTest
* 变量名、方法名: 首字母小写、后面每个单词首字母大写 adminTest
* 常量名: 全部大写 ADMIN
2、关键字
public
class
static
void。。。。。
3、字面值
100
"ABC"
'A'
4.14
true、FASE
字面值就是数据
数据显示纾解中是分名别类,他在计算机中也是有类型的【数据类型】
100 属于整数型字面值
“ABC” 属于字符串字面值
‘A’ 属于字符字面值
3.14 属于浮点型字面值
true、FASE 属于布尔字面值
4、变量
- 1、什么是变量
变量本质是哪个是内存的一块空间,这块空间,他有“名字”,“有数据类型”,“有字面值”
变量包含三部分:数据类型,名字,字面值【数据0】
变量是内存储存的最基本的单位
- 2、数据类型的作用:
不同的数据有不同的数据类型,不同的数据类型会分配不同大小的空间
数据类型是知道程序在运行阶段应该分配多大的空间
- 3、变量的要求:变量中储存的数据,必须和变量的数据类型保持一致,不一致时报错
- 4、申明变量的语法:
数据类型 变量名
数据类型:int btye short char long double float 布尔
申明变量后如何赋值:
语法要求: 变量名=字面值
这个可以重新赋值; int i =0 i=100 这个重新复制了
申明变量和赋值一起
语法要求: 数据类型 变量名= 字面值 int i=0 ;int i =100; 这样是不行的,这个是重新申明可一个变量
变量赋值后,可以重新赋值,变量值可以变化,有了变量后空间可以得到重复利用
- 5、通常访问一个变量包括两种方式:
* 第一种 get 获取值
* 第二种 set 设置值
- 6、变量必须先申明在赋值才能访问
1、关于java中的变量
1、在方法体中java代码,是遵守自伤而下的顺序执行的
2、变量的作用域:变量的有效范围:
只需要记住一句话:
出了大括号就不认识了
eg:
int i=0;
for (i = 0; 1 < 10; i++) {} 可以访问i
for (int i = 0; 1 < 10; i++) {} 不能访问i
2、变量的分类:
-
局部变量:在方法体内申明的变量称为 局部变量
-
成员变量:在方法体外申明的变量称为 成员变量
-
类变量(静态变量)
类变量也称为静态变量,在类中以 static 关键字声明,但必须在方法之外。
无论一个类创建了多少个对象,类只拥有类变量的一份拷贝。
静态变量除了被声明为常量外很少使用,静态变量是指声明为 public/private,final 和 static 类型的变量。静态变量初始化后不可改变。
静态变量储存在静态存储区。经常被声明为常量,很少单独使用 static 声明变量。
静态变量在第一次被访问时创建,在程序结束时销毁。
与实例变量具有相似的可见性。但为了对类的使用者可见,大多数静态变量声明为 public 类型。
默认值和实例变量相似。数值型变量默认值是 0,布尔型默认值是 false,引用类型默认值是 null。变量的值可以在声明的时候指定,也可以在构造方法中指定。此外,静态变量还可以在静态语句块中初始化。
静态变量可以通过:ClassName.VariableName的方式访问。
类变量被声明为 public static final 类型时,类变量名称一般建议使用大写字母。如果静态变量不是 public 和 final 类型,其命名方式与实例变量以及局部变量的命名方式一致。
5、数据类型:
5.1、基本数据类型:
1、byte:
byte 数据类型是8位、有符号的,以二进制补码表示的整数;
2、short:
short 数据类型是 16 位、有符号的以二进制补码表示的整数
3、int:
int 数据类型是32位、有符号的以二进制补码表示的整数;
4、long:
long 数据类型是 64 位、有符号的以二进制补码表示的整数;
5、float:
float 数据类型是单精度、32位、符合IEEE 754标准的浮点数;
6、double:
double 数据类型是双精度、64 位、符合 IEEE 754 标准的浮点数;
7、boolean:
boolean数据类型表示一位的信息;
8、char:
char 类型是一个单一的 16 位 Unicode 字符;
注意:字符串不属于基本数据类型
5.2、引用数据类型
String
Integet 等
所有引用类型的默认值都是null。
转义字符串:
char c1='\n'; //是一个换行符: enter
System.out.println(ii); //输出之后换行
System.out.print(ii); //输出之后不换行
char c1='\t'; //是一个制表符: tab
char c1='\\'; = \
char c1='\''; = '
反斜杠具有转移功能,讲第二个单引号转换成普通的单引号的字符
System.out.println("\"fff\""+c1); "fff"\)
5.3、数据类型的转换
1、八种疾病数据类型中除了布尔类型之外,的7种类型都可以转换
2、小容量向大容量转换,称之为自动类型转换,容量从小到大排序 自动转换
2.1、byte < short(char) < int < long < float < double
2.2、任何浮点类型不管站用多少个字节,都不整数型容量大
char和short可表示的种类数量相同,但chat可以取更大的正整数
2.3、大容量转换成小容量,叫强制类型转换,需要加强制类型转换符,程序才能编译,但肯会随时精度 强制类型转换
2.4、当整数字面值没有超过byte ,short,char可以取值的范围,可以直接赋值给byte short char类型的变量
byte short char 混合运算时,线各自转换成int类型在计算
byte a = 20;
short b =1000;
int c= 1000;
long d=c;
int e=(int)d;
double f=10/3;
long g= 10;
以上都是编译通过的
6、运算符
算数运算符:
a + b = 30
a - b = -10
a * b = 200
b / a = 2
b % a = 0
c % a = 5
a++ = 10
a-- = 11
d++ = 25
++d = 27
关系运算符
a == b = false
a != b = true
a > b = false
a < b = true
b >= a = true
b <= a = false
逻辑运算符
a && b = false
a || b = true
!(a && b) = true
三元运算符
variable x = (expression) ? value if true : value if false
// 如果 a 等于 10 成立,则设置 b 为 20,否则为 30
b = (a == 10) ? 20 : 30;
System.out.println( "Value of b is : " + b );
7、控制语句
选择结构语句
if
if(布尔表达式 1){
//如果布尔表达式 1的值为true执行代码
}else if(布尔表达式 2){
//如果布尔表达式 2的值为true执行代码
}else if(布尔表达式 3){
//如果布尔表达式 3的值为true执行代码
}else {
//如果以上布尔表达式都不为true执行代码
}
if(){}else {};
switch:
语法:switch(int或者String类型的字面值或者变量)
public class Test {
public static void main(String args[]){
//char grade = args[0].charAt(0);
char grade = 'C';
switch(grade)
{
case 'A' :
System.out.println("优秀");
break;
case 'B' :
case 'C' :
System.out.println("良好");
break;
default :
System.out.println("未知等级");
}
System.out.println("你的等级是 " + grade);
}
}
大括号中的数据不是必须的
循环接口语句
for
for(初始化; 布尔表达式; 更新) {
//代码语句
}
增强for循环
for(声明语句 : 表达式)
{
//代码句子
}
while
while( 布尔表达式 ) {
//循环内容
}
do while
do {
//代码语句
}while(布尔表达式);
o…while 循环和 while 循环相似,不同的是,do…while 循环至少会执行一次。
控制顺序语句
break
break 主要用在循环语句或者 switch 语句中,用来跳出整个语句块。
break 跳出最里层的循环,并且继续执行该循环下面的语句。
continue
continue 适用于任何循环控制结构中。作用是让程序立刻跳转到下一次循环的迭代。
在 for 循环中,continue 语句使程序立即跳转到更新语句。
在 while 或者 do…while 循环中,程序立即跳转到布尔表达式的判断语句。
8、方法
方法介绍
1、方法时定义在类体当中的
2、什么是方法:方法就是一个代码片段,,并且这个代码片段可以完成某个功能,并且可以重复使用
3、方法体中不能再定义一个方法
方法的的写法:
修饰符 返回值类型 方法名(参数类型 参数名){ 括号中的是形式参数列表
...
方法体
...
return 返回值;
}
关于修饰符:
1、可选项,不是必须的
2、目前统一写成 public static
3、方法中带static 关键字的话,如何调用
类名.方法名(实际参数列表)
返回值类型:
1、一个方法是可以完成某个特定功能的,这个功能结束之后大多数都是需要
返回最终结果的,执行结果肯能是一个存在的数据,而这个具体的数据就是返回值类型
2、java的返回值类型有哪些
java任意一种类型都可以,包括基本数据类型和所有的引用数据类型
3、形式参数列表:简称形参
形式参数列表是局部变量:int A ;等于
程序的入口:主方法
public static void main(String[] args) {}
形式参数列表: String[]是一种应用数据类型 args 是一个局部变量
其本质和自己写的方法没有区别
接收方法的返回值:比如计算两个数的和,返回值类型为int,所以用int类型的数据接收
int i = sum(1,2)
方法的重载:overload 方法名相同参数不同
功能相似的时候,方法名可以相同
在同一个类中
方法名相同
参数列表不同
数量不同
顺序不同
类型不同
方法的重写 (方法的覆盖):方法名相同,参数列表相同(override )的继承
在重写方法时,需要遵循以下的规则:
(一) 父类方法的参数列表必须完全与被子类重写的方法的参数列表相同,否则不能称其为重写而是重载。
(二) 父类的返回类型必须与被子类重写的方法返回类型相同,否则不能称其为重写而是重载。
(三) Java中规定,被子类重写的方法不能拥有比父类方法更加严格的访问权限。编写过Java程序的人就知道,父类中的方法并不是在任何情况下都可以重写的,当父类中方法的访问权限修饰符为private时,该方法只能被自己的类访问,不能被外部的类访问,在子类是不能被重写的。如果定义父类的方法为public,在子类定义为private,程序运行时就会报错。
(四) 由于父类的访问权限修饰符的限制一定要大于被子类重写方法的访问权限修饰符,而private权限最小。所以如果某一个方法在父类中的访问权限是private,那么就不能在子类中对其进行重写。如果重新定义,也只是定义了一个新的方法,不会达到重写的效果。
(五) 在继承过程中如果父类当中的方法抛出异常,那么在子类中重写父类的该方法时,也要抛出异常,而且抛出的异常不能多于父类中抛出的异常(可以等于父类中抛出的异常)。换句话说,重写方法一定不能抛出新的检查异常,或者比被重写方法声明更加宽泛的检查型异常。例如,父类的一个方法申明了一个检查异常IOException,在重写这个方法时就不能抛出Exception,只能抛出IOException的子类异常,可以抛出非检查异常。同样的道理,如果子类中创建了一个成员变量,而该变量和父类中的一个变量名称相同,称作变量重写或属性覆盖。但是此概念一般很少有人去研究它,因为意义不大。
方法的递归:这样就死循环了
public static void main(String[] args) {
m1(1);
}
public static void m1(int a){
m1(1);
}
构造方法
方法的内存图分析
- 方法一的内存图分析
public class Student {
int age;
String name;
address add;
int id;
}
public class address {
String street;
String city;
int Zipcode;
}
=========================方法一:或者以下写法,结果都是一样的======================
public static void main(String[] args) {
Student s = new Student();
int stuage=s.age;
s.add = new address();
s.add.city="上海";
System.out.println(s.add.city);
}
// new address(是一个对象)
=========================方法二:或者以下写法,结果都是一样的======================
//a是一个引用,也是一个局部变量
public static void main(String[] args) {
Student s = new Student();
address a = new address();
s.add= a;
a.city="山海";
System.out.println(s.add.city);
}
- 方法二的内存图分析
jvm的介绍:
1、jvm(java虚拟机)主要包含三块内存空间,分别是:栈内存堆内存,方法去内存
2、堆内存和方法区内存个有一个,一个线程一个站内存
3、方法调用的时候,发方法所需额内存空间在栈内存中分配,成为压栈,方法取执行结束后,该方法所属的内存空间释放,称为弹栈
4、栈中主要存储的是方法体当中的局部变量
5、方法的代码片段以及整个类的代码片段都会被储蓄到方法去内存当中,在类加载的时候这些代码会被加载
6、在程序执行过程中使用new运算符创建java对象,储蓄在堆内存当中,对象内部有实力变量,所以实例变量储存在堆内存当中
7、变量分类:
局部变量【在方法体中声明】
成员变量【在方法体外申明】
* 实例变量【前面修饰没有static】
* 静态变量【前面修饰有static】
8、静态变量储蓄在方法区域内存当中
9、三块内存中变化最频繁的是栈内存,最优数据的是方法区域内存,垃圾回收期主要针对的是堆内存
10、垃圾回收期【自动垃圾回收机制,gc机制】什么时候考虑将某个java对象的内存回收
当堆内存的java对象成为垃圾数据的时候, 会被垃圾回收器回收
什么时候堆内存的家吧对象会变成垃圾
没够更多的引用指向他的时候
这个对象无法被方位,应为方位对象只能通过引用的方式访问
空指针:
public static void main(String[] args) {
Student s = new Student();
int stuage=s.age;
address a = new address();
a=null;
s.add= a;
a.city="山海";
System.out.println(s.add.city);
}
如果a=null,会报空指针异常,空引用访问“实例”相关的数据会出现空指针色
三、面向对象,面向过程编程
1、类的定义
语法结构
修饰符列表 class 类名{
属性;
方法
}
引用数据类型
String
student --前提是自己编写了student class类
类体=属性+方法
属性【储存数据采用变量的形式】
由于变量定义在类体重,方法体之外,这种变量称为“成员变量”
所有学生都有学号信息
每个学生的学号不通
所以要访问这个学生的学号必须选穿件对象,通过对象去访问学号
学号信息不能直接通过类去访问,所以这种“成员变量称职为”:实例变量
对象有被称为实例,实例变量右边称之为“对象的变量”
不创建对象,这个学生的编号的内存空间是不存在的,只有穿件对象,内存空间才存在
2、创建对象:
public class Test {
int i=10;//这个称职为实例变量
Student s = new Student();
}
通过一个类可以实例化N个对象
实例化对象的语法 new Student();
new 是java语言当时的一个运符
new运算符的作用是创建对象,在jvm堆内存中开辟新的空间
方法去的内存:在类的加载的时候,class字节代码片段比加载到该内存空间中
栈内存(局部变量):方法代码片执行的时候,会给改方法分配内存空间,在栈内存中压栈
堆内存: new的对象在堆的内存中储存
成员变量没有手动赋值的话,系统会自动赋值:
student是一个引用数据类型
new student是一个学生对象
s是一个局部变量,在栈内存中压栈
s是一个引用
java语言中,程序员不能直接操作堆内存,java没有指针,
java语言中,程序员只能通过“引用”去访问堆内存中对象内部的实例变量
3、访问实例变量的语法
//读数据: 引用.变量名
//修改数据: 引用.变量名=值
public class Test {
public static void main(String[] args) {
Student s = new Student();
int stuage=s.age;
System.out.println(stuage);//间接性读取
System.out.println(s.age);//直接读取
s.age=10;
System.out.println(s.age);// 修改数据
}
}
局部变量在栈内存中储存
成员变量中的实例便利子安在栈内存的家吧对象内部储存
实例变量不能采用 类名.变量名 只能通过引用来进行访问
public static void main(String[] args) {
//對於當前程序來說,student类中的属性是可以随意放问的,缺乏安全性;
Student s = new Student();
int stuage = s.age;
s.name="王思聰";
s.add = new address();
s.add.city="上海";
System.out.println(s.add.city);
System.out.println(s.name);
}
4、面向对象的三大特征
封装
继承
多态
封装步骤:
1、所有属性私有化,使用private关键字进行修饰,private表示私有的,修饰的所有数据只能在本类中进行访问
2、一个属性通常访问的时候包括几种方式
第一种:想读取某个属性 get
第二种:想修改某个属性 set
构造方法:
1、构造方法又被称为构造函数、构造器
2、构造方法的语法
修饰符列表 构造方法名(形式参数列表){
构造方法体
}
构造方法的注意向:
2.1、对于构造方法来说,构造方法不需要指定返回值类型
2.2、加上了返回值类型就变成普通方法了
2.3、构造方法的方法名必须和当前的类名相同
普通方法的语法:
修饰符列表 返回值类型 方法名(形式参数列表){
构造方法体
}
3、构造方法的作用:
构造方法存在的意义,通过构造方法的调用,可以创建对象
1、创建对象
2、创建对象的同时,初始化实例变量的内存空间【给实例变量赋值】
4、构造方法的调用
普通方法的调用:方法修饰符中有static的时候
类名.方法名(实参列表)
方法修饰符中没有static的时候
引用.方法名(实参列表)
构造方法的调用:
new 构造方法名(实际参数列表)
构造是有返回值的,但被影藏了,作用是完成对象的创建
5、为什么构造方法的返回值类型不同写
5.1、每一个方法实际执行结束后都有返回值类型,,但这个return 值;这样的语句不需要写,构造方法结束后java程序自动返回值
5.2、并且返回值类型是狗仔方法所在类的诶下,由于构造方法的类型就是本事,所以返回值类型不需要写
5.3、一个默认的类都会有一个默认的五参数的构造方法,一旦编写了有参的构造方法,无参的构造方法不会被影藏;
5.4、构造方法支持重载机制,在一个类中编写多个构造方法,显然这个构造方法已经形成重载机制
在一个构造方法中,可以用this(1,5,6);来调用实参不同的构造方法。
重点:this();这种语法只能出现在第一行。
也就是说:一个构造方法中只能调用一个构造方法
5、参数传递
1、对象和引用
1.1:对象和引用的概念
*对象:目前用new运算符在堆内存中开辟的空间称为对象
*引用:是一个变量,,不一定是局部变量,还可能是成员变量。引用保存了内存地址,指向了对内存当中的一块空间
*所有实例相关的的访问必须通过“引用”的方式
*引用可以是局部变量,也可以是实例变量
2、参数传递
主要研究和学习的是:方法在调用的时候,涉及到参数传递的问题,到底是怎么传递的呢?
int i =10;
method(i);
给method传递一个i变量,传递的是什么?
-传递的是i变量中的10
i变量是局部变量,本身也占有内存空间,
所以i变量本身也有内存地址,i变量中保存的是10这个字面值
2.1、:参数传递
]
把main方法中的内存地址传给了add:传递u给add方法的时候,实际上产地的是u变量保存的值,只不过这个是是java对象的内存地址
add(u) 等同于:add(0x1234)
1、方法的实参形参也可以是构造函数
public static void add(User u){
u.age++;
}
传入的是内存地址,修改以后永久修改,不需要return重新修改
注意:u是一个引用,是局部变量,u所指向的是堆内存的一块空间
2、方法调用的时候传递的是变量中保存的“值”
6、this关键字
]
一:什么时候可以使用this关键字:
1、this关键字:神奇
-this是一个关键字,翻译为这个
-this里面保存了内存地址,指向自身对象
2、引用中:zhangSan.name
在User类中,写一个set方法
public void setName(int name){
//name = name; 报错
this.name = name;
//this=zhangSan,保存了一个内存地址,
指向了自己。
}
3、this是一个引用,this是一个变量,this变量中保存了自己的内存地址,this存储在JVM的堆内存的对应对象中。
100个对象就有100个this
4、当使用zhangSan去访问该对象时,整个过程中出现的this就等于zhangSan
5、没有static关键字的方法被称为实例方法
没有static关键字的变量被称为实例变量
必须要使用引用.方法名()
static的解释:
6、注意,当一个行为/动作执行的过程当中是需要对象参与的,那么这个方法一定要定义为“实例方法”,不要带static关键字
7、this可以用在实例方法中,代表正在执行这个方法的对象
8、this在多数情况下可以省略不写。由于上面的name代表的是当前对象的实例变量,可以省略
9、.static的方法调用不需要对象,直接使用类名,执行过程中直接类名.方法名
例子:
public class constuntur
{
String name;
public void shopping(){
//代表正在执行的这个对象
System.out.println("谁在购物:"+this.name);//c1或者C2谁谁调用就是谁
}
}
public class constomertest {
public static void main(String[] args) {
constuntur c1=new constuntur();
c1.name="张三";
c1.shopping();
constuntur c2=new constuntur();
c2.name="李四";
c2.shopping();
}
}
]
结论:带有static的方法不能直接访问“实例变量和 实例方法”
通过无参的构造方法来调用有参的
public class constuntur {
private String name;
public void shopping() {
System.out.println("谁在购物:" + name);
}
public constuntur(String name) {
this.name = name;
}
public constuntur() {
方式1 // new constuntur("lei"); 通过这种方式调用无参的构造方法会穿件两个对象
//以上代码可以通过调用另一个构造方法类完成
//但前提是不能穿件新的对象
方式2 this("lei");//只当前的有参的构造方法,避免通过午餐的构造方法穿件了性的对象
}
public static void main(String[] args) {
constuntur c1=new constuntur();
c1.shopping();
constuntur c2=new constuntur("lei");
c2.shopping();
}
this可以用在那
可以使用午餐的构造方法来
二、this什么时候不能省略
1、用来区分实例变量和局部变量的时候不能省略
public constuntur(String name) {
this.name = name;
}
补充:
1、什么时候出现空指针异常?
空引用访问实例相关的数据,因为相关的数据就是对象相关的数据,
空引用访问时没有相关数据,空指针异常。
2、带有static的方法,可以采用类名.方法名的方式访问,也可以用引用.方法名的方式来访问,
只不过用不到这个对象,没有意义,但也能正常运行,不会出现空指针异常
7、Super关键字的使用(出现在继承中)
当需要在子类中调用父类的被重写方法时,要使用super关键字。
(1)super能出现在实例方法和构造方法中。
(2)super的语法是“super.”和“super()”。
(3) super不能出现在静态方法中。
(4) super大部分情况下是可以省略的。
public class MyTest {
public static void main(String[] args) {
Cat c1 = new Cat(3);
System.out.println("名字:" + c1.getName());
System.out.println("年龄:" + c1.getAge());
}
}
//父类,Animal类
class Animal {
//私有属性:名字
private String name;
//setter and getter
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
//构造函数
public Animal() {
}
public Animal(String name) {
this.name = name;
}
}
//子类,Cat类
class Cat extends Animal{
//私有字段:年龄
private int age;
//setter and getter
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
//构造函数
public Cat() {
}
public Cat(String name, int age) {
super(name);
this.age = age;
}
}
8、static关键字
一旦使用static修饰成员方法,那么这就成为了静态方法。静态方法不属于对象,而是属于类的。
如果没有static关键字,那么必须首先创建对象,然后通过对象才能使用它。
如果有了static关键字,那么不需要创建对象,直接就能通过类名称来使用它。
无论是成员变量,还是成员方法。如果有了static,都推荐使用类名称进行调用。
静态变量:类名称.静态变量
静态方法:类名称.静态方法()
注意事项:
- 静态不能直接访问非静态。
原因:因为在内存当中是【先】有的静态内容,【后】有的非静态内容。
“先人不知道后人,但是后人知道先人。” - 静态方法当中不能用this。
原因:this代表当前对象,通过谁调用的方法,谁就是当前对象。
1.实例变量:
*1.每一个对象都有对应的一个实例变量,要开辟大量内存空间。
如果有一个中国人类
下面country一个带静态一个不带的话,是为了减少内存空间,带static的country储存在方法区中
不带static的话储存在栈中(个人认为都杀不多)
public class Chinese {
int id;
String name ;
static String country="中国"; //带static
public Chinese1() {
}
public Chinese1(int id, String name) {
this.id = id;
this.name = name;
}
public class Chinese {
int id;
String name ;
String country;
public Chinese() {
}
public Chinese(int id, String name, String country) {
this.id = id;
this.name = name;
this.country = country;
}
=country带static=============================
public static void main(String[] args) {
//看起来都一样,创建了太多相同的对象,浪费内存空间
Chinese1 c =new Chinese1(1,"詹三");
System.out.println(c.id+c.name+Chinese1.country);
Chinese1 c1 =new Chinese1(2,"李四");
System.out.println(c1.id+c1.name+Chinese1.country);
}
=country不带static=================
public static void main(String[] args) {
//看起来都一样,创建了太多相同的对象,浪费内存空间
Chinese c =new Chinese(1,"詹三","中国");
Chinese c1 =new Chinese(2,"李四","中国");
Chinese c2 =new Chinese(3,"王五","中国");
}
1.关于java中的static关键字:
1.static单词:静态的
2.static修饰的是静态方法
3.static修饰的变量都是静态变量
4.所有的static修饰的元素都成为静态的,都能使用 “类名.”的方式访问,也能通过“引用.”的方式访问
2、可以使用static关键字来定义“静态代码块”
1.语法格式:
static{
java语句
}
2、静态代码块在类加载的时候执行,并且只执行一次
3、静态代码块在一个类中可以编写多个,并且遵循自上而下的方式进行
4、为什么要学?有什么好处?
静态代码块的作用是什么?怎么用?什么时候用?
*1.和实际需求有关
(1)编写日志。要求在类加载的那一刻执行代码完成日志的记录。
那么这段记录日志的代码就可以编写到静态代码块中,完成日志记录
*2.静态代码块是java为程序员准备的一个特殊时刻,这个特殊的时刻被称为类加载时刻。
若希望在此刻执行一段特殊的程序,这段程序可以直接放到静态代码块中
5、通常在静态代码块中完成数据准备工作。例如:初始化连接池,解析XML配置文件
6、静态代码块(使用的非常少)
class Static1 {
static {
System.out.println("类加载1");
}
static {
System.out.println("类加载2");
}
public static void main(String[] args) {
System.out.println("执行主方法");
}
}
2.在构造方法之前执行一次。
3.可以编写多个,也是遵循自上而下的顺序依次执行
4.这个时机被称为:对象初始化时机
7、实例代码块(用的非常少)
]
]
2.在构造方法之前执行一次。
3.可以编写多个,也是遵循自上而下的顺序依次执行
4.这个时机被称为:对象初始化时机
8、方法什么时候声明为静态的?
方法描述的是动作,当所有对象执行这个动作的时候,最终产生的影响是一样的,那么这个
动作已经不再属于某一个对象动作了,可以将这个动作提升为类级别的动作,模板级的动作
*例如:买东西,每个人买的东西不一样,结果不同,定义实例方法a
注意:静态方法中无法直接访问实例变量和实例方法
2.大多数方法都定义为实例方法,一般一个行为或者一个动作在发生的时候,都需要对象的参与
但也有例外:大多数“工具类”中的方法都是静态方法,因为工具类就是方便编程,为了方便方法的调用
继承
四、关于java语言中的继承
1、继承的介绍
-
1.继承是面向对象三大特征之一:封装,继承和多态
-
2.继承基本的作用是:代码复用。但是继承最重要的作用是:有了继承才有了以后方法的覆盖和多态这种机制,减少代码的编写
-
3.继承语法格式:
[修饰符列表] class 类名 extends 父类名{
类体(属性+方法)
}
-
4.java语言当中的继承只支持单继承,一个类不能同时继承很多类,只能继承一个类
-
5.关于继承中的术语:
B类继承A类 其中:A类称为父类、基类、超类、superclass
B类称为:子类、派生类、subclass -
6.在java语言当中子类继承父类都继承那些数据呢?
* 私有的不支持继承 private * 构造方法不支持继承 * 其他数据都支持继承,都可以被继承
-
7.虽然java语言当中只支持单继承,但是一个类也可以以间接继承其他类
任何一个类默认继承object类
c extends B{
}
B extends A{
}
A extends T{
}
C直接继承B类,但是C类间接继承T A B类
-
8.当一个类没有显示地继承任何类,该类默认继承JAVASE库当中的java.lang.Object类
java语言中任何一个类都有Object类中的特征
-
9.私有的不继承,其他的可以继承,直接把里面的方法拿过来用。
Super关键字的使用(出现在继承中)
当需要在子类中调用父类的被重写方法时,要使用super关键字。
2、方法覆盖
1.Overload回顾方法重载
1、方法重载又被称为overload
2、方法重载什么时候使用?
在同一个类当中,方法完成的功能是相似的,建议方法名相同。
3、什么条件满足后构成方法重载?
在同一个类当中,方法名相同,参数列表不同:类型、顺序、个数
4、方法重载和什么无关
* 和方法的返回值无关
* 和方法的修饰符列表无关
2.方法覆盖Override(方法重写,Overwrite)
-
1.什么时候使用方法重写?
当父类中的方法已经无法满足当前子类的也无需求,子类有必要将父类继承过来的方法进行重写(覆盖); -
2、什么条件满足后会发生方法重写呢?
1、方法覆盖发生在具有继承关系的父子类之间
2、返回值类型相同,方法名相同,形参列表相同就发生覆盖。
3、一定调用覆盖后的方法
4、访问权限不能更低,可以更高
public class Animail {
public void move(){
System.out.println("动物在移动");
}
}
public class Cat extends Animail{
//重写父类的move
public void move(){
System.out.println("cat在移动");
}
}
public class Dog extends Cat{
//重写父类的move
public void move(){
System.out.println("dog在移动");
}
}
public class TestAnimail {
public static void main(String[] args) {
Animail a= new Animail();
a.move();
Cat c= new Cat();
c.move();
Dog d= new Dog();
d.move();
}
}
没重写前都是动物在移动,显然无法实现cat和dog的业务
重写后
父类中:public
子类中只能用public
父类中private
子类中可以public
*抛出异常不能更多,只能更少。
*3、建议方法重写的时候复制粘贴
*4、注意:
私有方法不能继承,所以不能覆盖
构造方法不能继承,所以不能覆盖
静态方法不存在覆盖。
覆盖只针对方法,不谈属性。
3、多态
1.多态的语法:
1、Animal、Cat和Bird三个类之间的关系:
Cat继承Animal
Bird继承Aninal
Cat和Bird没有任何继承关系
2.关于多态的几个概念
向上转型(upcasting)
子类型转换为父类型
又被称为:自动类型转换
向下转型(downcasting)
-父类型转成子类型
又被称为强制类型转换【需要添加强制类型转换符】
转型的前提:*要想通过编译,必须要有继承关系,没有继承关系,程序是无法通过的。
3.Animal a2 = new Cat();
可以,*Animal和Cat之间存在继承关系,Animal是父类,Cat是子类
*new Cat()创建的对象类型是Cat,a2这个引用的数据类型是Animal,可见他们进行了类型转换
*子类型转换为父类型,向上转型,自动类型转换
4.java程序永远都分为编译阶段和运行阶段
先分析编译阶段,再分析运行阶段,编译无法通过,无法运行
*编译阶段检查a2这个引用数据类型Animal,由于Animal.class
字节码中有move()方法,所以编译通过了。
这个过程我们称为静态绑定,编译阶段绑定
只有静态绑定成功之后才能运行
*运行的时候,JVM堆内存当中真实创建的对象是Cat对象,那么以下程序在运行阶段
一定会调用Cat对象的Move()方法,此时发生了程序的动态绑定
5.无论Cat类有没有重写move方法,运行阶段一定调用的是Cat对象的move方法,应为底层真是对象就是Cat对象
6.父类型引用指向子类型对象这种机制导致程序存在编译阶段绑定和运行阶段绑定两种不同的形态/状态
这种机制可以成为一种多态语法机制。
7.静态绑定成功后才能进行动态绑定。
4、多态进阶:
1.不存在继承关系的类型:
Bird c1 = Cat();
Bird Cat 都属于Animal的子类,但是cat and bird之间没有继承关系
所有不能
2.如果说要调用父类型没有的方法?
Animal a1 = new Cat();
Cat里有一个catchMouse方法;
a1无法直接调用,应为a2的类型是Animal,没有这个方法怎么办?
*可以将a1强制类型转换为Cat
a1的类型是Animal(父类),转换为Cat类型(子类),被称为向下转型(downcasting)
public class Animail {
public void move(){
System.out.println("动物在移动");
}
}
public class Cat extends Animail{
public void move(){
System.out.println("cat在移动");
}
}
public class Dog extends Animail{
public void move() {
System.out.println("dog在移动");
}
//这个个在子类中特有的方法
public void dogcat(){
}
}
public class TestAnimail {
public static void main(String[] args) {
Animail a= new Animail();
a.move();
Cat c= new Cat();
c.move();
//父类型的应用允许执行子类型的对象
Animail d= new Dog();
d.move();//编译器的绑定,无法访问到dogcat
Dog c2= (Dog)d; //想要访问的话的做强制类型转换
//d.dogcat();
c2.dogcat();
}
}
注:向下转型也需要两种类型之间有继承关系。要加上强制类型转换符
-
什么时候需要向下转型呢?
当调用的方法或者访问的类型是子类型中特有的,在父类型当中不存在,必须进行向下转型
-
怎么转?
Cat a2 = (Cat)a1;
3.类型转换异常:如果说有一个代码:
Animal a3 = new Bird();
Cat c3 = (Cat)a3;
-
编译阶段没问题,因为编译器认为a3是Aninal(父),转换为c3(子)
语法合格 -
程序虽然编译通过了,但是程序在运行阶段会出现异常,应为JVM堆内存
当中真实存在的是Bird类型,Bird类型无法转换为Cat对象,因为两种类型没有继承关系
此时出现了著名的异常:java.lang.ClassCastException异常:类型转换异常
这种异常只有在强制类型转换的时候出现异常
怎么避免这种异常?instanceof 的使用
- 1、以上异常只有在强制类型转换的时候会发生,也就是说,向下转型存在安全隐患
- 2、向上转型只要能编译通过,运行一定不会出问题
- 3、向下转型编译通过,运行可能出问题
- 4、怎么避免乡下转型出现的类型转换异常?
使用instanceof运算符可以避免以上异常 - 5、instanceof怎么用?
5.1、语法格式
引用 instanceof 数据类型名
5.2、以上运算符的执行结果类型是布尔类型,结果可能是true/false
5.3、关于运算结果true/false
假设(a instanceof Animal)
true:表示a这个引用指向的对象是一个animal类型
false:表示a这个引用只想的对象不是一个animal类型
- 6、如果想要安全执行向下转换:
//Cat c3 = (Cat)a3;
if (a3 instanceof Cat){
Cat c3 = (Cat)a3;
}else{
System.out.println("错误!");
}
-
7.java规范中要求,在进行强制类型转换之前,建议使用instanceof运算符进行判断,避免ClassCaseExpection异常的出现
4.调试debug的方法:断点
5、多态在实际开发中的作用
1.多态在实际开发中的作用?(以主人喂养宠物为例说明)
*1.分析:主人喂养宠物这个场景要实现需要进行类型的抽象
-主人【类】
-主人可以喂养宠物,所以主人有喂养这个动作
-宠物【类】
-宠物有吃东西的动作
*2.定义好类,然后将类实例化为对象+,给一个环境驱使,让哥哥对象之间协作起来形成一个系统
*3.提高程序的扩展力:
降低软件的耦合度【解耦合】,提高程序的扩展力
master主人类面向一个抽象的Pet类型,而不是面向具体的Dog、Cat类型
在使用的时候可以使用向上转型,子类转换为父类。
2.即多态的作用是降低程序耦合度,提高扩展力。
*核心:面对抽象编程,不要面向具体编程。
面向对象的例子
public class Cat extends Pet {
//重写了Pet
public void eat(){
System.out.println("猫爱吃鱼");
}
}
public class Dog extends Pet {
//重写了Pet
public void eat() {
System.out.println("宠物小狗吃骨头");
}
}
public class Master {
/*
以下这个方法扩展了很差,没使用多台时,每个都很麻烦
public void feed(Cat c){
c.eat();
}
public void feed(Dog d){
d.eat();
}
*/
//使用多态
//Pet pet=new Cat ;Pet pet=new Dog 是一个父类型的应用,扩展性强
//mast面向的是一个抽象的变成好处是耦合度低,扩展性极强
public void feed(Pet pet){
pet.eat();
}
}
//使用多态是新增一个类
public class Pet {
public void eat(){
}
}
public class Test {
public Test() {
}
public static void main(String[] args) {
Master zhansan = new Master();
zhansan.feed(new Cat());
zhansan.feed(new Dog());
}
}
6、final关键字
1、final是一个关键字,表示最终的,不可变的.
2、final修饰的类无法被继承
3、final修饰的方法无法被覆盖
4、final的变量一旦赋值,无法改变
5、final修饰的实例变量??
实例变量中,final int i;报错
final int i =10;不报错
SUN公司规定,实例变量使用final时必须自行赋值,不能使用默认值。
解决: 1.直接赋值 final int i =10
2.在方法中赋值public User(){
this.num = 1;
}
本质上是一样的。
6、final的引用?
看源码:对开发进行帮助
final关键字
1、final的引用:一旦被final修饰的引用指向一个对象,就不能改指向的对象了,并且这个对象无法被设置成null,除非main方法结束,
这个对象就永远不会被垃圾回收器回收。
2、但是这个对象中保存的属性可以被修改(除非这个属性被final修饰)
final关键字
1、final修饰的实例变量是不可变的,一般和static一块使用,被称为"常量"
2、常量的定义语法格式:
public static final 类型 常量名 = 值;
3、java规范中要求所有常量的名字全部大写,每个单词之间使用下划线连接。
7、package import
包和import
1、关于java语言当中的包机制:
1.1:包又称为package,引入package这种语法机制主要是为了方便程序的管理。
不同的功能的类被分门别类放到不同软件包当中,便于维护
1.2: 怎么定义包?
-在java源程序的第一行上编写package语句。
-package只能编写一个语句
-语法结构:
package 包名;
1.3 包名的命名规范
公司的域名倒叙 + 项目名 + 模块名 + 功能名;
采用这种方式重名的概率较低,应为公司域名具有全球唯一性
包名要求全部小写,包名也是标识符,必须遵守标识符的命名规则
一个包将来对应一个目录
例如:com.bjpowernode.oa.user.service;
org.apache.tomcat.core【目录之间用.隔开】
1.4使用了package机制之后怎么编译运行呢?
-使用了该机制后,类名不再是Test01了,类名是:
com.bjpowernode.javase.day11.Test01
-编译 javac java源文件路径(在硬盘上生成一个class文件)
-手动方式创建目录com/bjpowernode/javase/day11
把class文件放到指定目录下
-另一种方式:javac -d . java源文件
自动创建文件夹
2.关于import
调用方法/类的时候,若class文件在同一个包下可以省略包名
import com.bjpowenode.javase.day11.Test01;
之后就可以不带包名了!!!
结论:import语句用来完成导入其他类,同一个包下不用导入,不通报下
要导入import 类名;
import 包名.*;
需要在package之后,class之前
注意:java.lang.*不需要手动引用
lang:language语言包,是java语言的核心类,不需要手动引入
最终结论:
什么时候使用import?不再java.lang包下,又不再同一个包下,要import
访问控制权限 基础篇完结
1.访问控制权限修饰符:
1、访问控制权限修饰符来控制元素的访问范围
2、访问控制权限修饰符包括:
public 表示公开的,在任何位置都能访问
protected
缺省
private 私有的,只能在本类中访问a
3.可以修饰类、变量、方法....
protected int i =10;//受保护的
int j =1;//缺省的
有什么区别?
*1.protected同包下可以访问,子类可以访问
*2.缺省 子类可以访问
4.当希望某个数据希望子类可以使用,用protected修饰
修饰符的范围:
private < 缺省 < protected <public
5.注意,类只能采用public和缺省的修饰符进行修饰。
五、java进阶
1、final关键字
1、final的及简介
1、final是一个关键字,表示最终的,不可变的.
2、final可以修饰变量,方法,以及类
1、final修饰的类无法被继承
2、final修饰的方法无法被覆盖
3、final的变量一旦赋值,无法改变
2、final修饰的引用
3、final修饰的实例变量系统不能默认复制,需要手动赋值(直接赋值,或者在构造方法之前赋值)
常量:实际上常量和静态变量一样,区别在于
常量的值是不能变的
常量和静态变量,斗志储存在方法区域,都是在类加载的时候初始化
4、final总结:
1、final是一个关键字,表示最终的,不可变的.
2、final修饰的类无法被继承
3、final修饰的方法无法被覆盖
4、final的变量的值只能赋值一次
5、final修饰的实例变两必须手动初始化,不能采用系统的默认值
6、final修饰的实例变量一般和static联合使用,称为常量
2、类的抽象
/**
-
银行的帐户 ===== > 抽象类
-
储蓄卡类 信用卡类 =====>这个比做类,显示中不存在的
- 小明的储蓄卡 小花的储蓄卡 小明的信用卡 小花的信用卡 ====>这个层面比做对象
- 1、抽象类无法创建对象:类与类有些共同特征,将这些共同的特征经一步形成抽象类,由于类是不是不存在的,所有抽象类无法创建对象
- 2、抽象类属于引用数据类型
- 3、抽象类的定义:
-
修饰符 abstract class 类名{
-
类体;
-
}
- 4、抽象类无法创建对象的,所以只能用来继承
- 编写有参的构造方法,但没有无参数的构造方法,继承是默认是会继承无参数的构造方法(通过supper)
- super(参数):调用父类中的某一个构造函数(应该为构造函数中的第一条语句)
*/
抽象方法在父类中不能实现,所以没有方法体。
// 这就是一个抽象类
abstract class Animal {
// 动物会叫
public abstract void cry(); // 不确定动物怎么叫的。定义成抽象方法,来解决父类方法的不确定性。抽象方法在父类中不能实现,所以没有方法体。但在后续在继承时,要具体实现此方法。
}
3、Super关键字的理解
package day8;
import lombok.Data;
public class Super {
public static void main(String[] args) {
teach te = new teach("王五",20,"上海");
System.out.println("我的姓名是:"+te.getNane()+" 年龄:"+te.getAge()+" 工作:"+te.getWork());
}
}
@Data
class people{
private String nane;
private int age;
public people() {
System.out.println("调用的是无参的构造方法");
}
public people(String nane, int age) {
this.nane = nane;
this.age = age;
System.out.println("调用的是有参的构造方法");
}
}
@Data
class teach extends people{
private String work;
public teach() {
}
public teach(String name,int age,String work) {
super(name,age); //默认调用的是无参的构造方法 默认是会有super ()
this.work= work;
}
}
4、接口 interface
1、接口是一种引用数据类型
2、接口是完全抽象的
3、接口的基础语法:
【修饰符列表】 interface 接口名 {
}
4、接口和接口是可以继承的,并且支持多继承’
5、接口中有两部分内容:
1、一部分是常量
2、另一部分是抽象方法;
6、抽象方法的定义
// 这就是一个抽象类
抽象方法在父类中不能实现,所以没有方法体。
abstract class Animal {
// 动物会叫
public abstract void cry(); // 不确定动物怎么叫的。定义成抽象方法,来解决父类方法的不确定性。抽象方法在父类中不能实现,所以没有方法体。但在后续在继承时,要具体实现此方法。
}
7、接口中的方法的修饰符可以省略(public abstrac),接口中常量也可以省略 public static final
8、接口中的方法中不能有方法体
9、接口在开发中的应用:
1、类和类之间叫继承,类和接口之间叫实现
继承用extends关键字来完成
实现用implements来完成
这样写是有问题的,接口是抽象的而myMathImpi类不是抽的,方式一,在myMathImpi类前面加abstract ,或者重写接口中的方法
public interface MyMath {
double pi=3.14;
int sum(int a,int b);
int sub(int a,int b);
}
class myMathImpi implements MyMath{
//会把抽象方法继承过来
}
重写接口中的抽象方法
public interface MyMath {
double pi=3.14;
int sum(int a,int b);
int sub(int a,int b);
}
class myMathImpi implements MyMath{
//会把抽象方法继承过来//所以的重写
@Override
public int sum(int a, int b) {
return a+b;
}
@Override
public int sub(int a, int b) {
return a-b;
}
}
//实现接口中的方法
class test{
public static void main(String[] args) {
//面向对象编程
MyMath A= new myMathImpi();//父类型的引用指向子类型的对象
int resuat1 = A.sum(1,2); //实现一个接口,实现接口下的类
System.out.println(resuat1);
}
}
类和接口直接多实现
public interface X {
void m1();
}
interface Y1{
void m2();
}
interface Z1{
void m3();
}
class D implements X,Y1,Z1{
public void m1() {}
public void m2() {}
public void m3() {}
}
class ceshi{
public static void main(String[] args) {
X x= new D();
x.m1();
}
}
extends Animal implements同时存在
public class Test03 {
public static void main(String[] args) {
Flyable F = new cat();
F.fly();
}
}
class Animal{
}
interface Flyable{
void fly();
}
//动物的子类,
//flyable是一个接口,是一堆翅膀的接口,通过接口插在猫上,让猫可以飞翔
class cat extends Animal implements Flyable{
public void fly(){
System.out.println("飞猫可以起飞");
}
}
//如果有一个蛇类,可以不实现flyable,,不想实现就不去实现flyable,所以是一个可插拔的接口
class sank extends Animal{
public void pa(){
}
}
面向抽象的编程,父类比子类更抽象
public class Cat extends Pet {
//重写了Pet
public void eat(){
System.out.println("猫爱吃鱼");
}
}
public class Dog extends Pet {
//重写了Pet
public void eat() {
System.out.println("宠物小狗吃骨头");
}
}
public class Master {
/*
以下这个方法扩展了很差,没使用多台时,每个都很麻烦
public void feed(Cat c){
c.eat();
}
public void feed(Dog d){
d.eat();
}
//面向多态和面向对象区别主要是要在这里多加一个feed 狗的方法,一旦扩展性极差
*/
//使用多态
//Pet pet=new Cat ;Pet pet=new Dog 是一个父类型的应用,扩展性强
//面向pet父类编程,父类比子类更抽象的,不要面向具体编程,
//mast面向的是一个抽象的变成好处是耦合度低,扩展性极强
public void feed(Pet pet){
pet.eat();
}
}
//使用多态是新增一个类pet=宠物
public class Pet {
public void eat(){
}
}
/**
* 多态在实际开发中的作用
* 1、分析主人喂养宠物的场景,需要进行类型抽象
* 主人
* 主人可以喂养宠物
* 宠物(类)
* 宠物可以吃东西,所以宠物有吃的动作
* 定义好类,然后将类实例化对象,给一个环节驱动试一下
*/
public class Test {
public static void main(String[] args) {
Master zhansan = new Master();
/*
Cat tom =new Cat();
zhansan.feed(tom);
Dog erha =new Dog();
zhansan.feed(erha);
*/
//或者简写成下面的
zhansan.feed(new Cat());
zhansan.feed(new Dog());
}
}
接口在开发中的作用:
注意:接口在开发中的作用,类似于多态在开发中的作用
多态:面向抽象编程,不要面向具体编程,父类是比子类更抽象的
比如猫。狗,主人,喂养这些:
面向抽象编程换句话说可以修改为:面向接口编程
顾客有一个菜单:以后凡是能使用hsa a 来描述的,统一属性的方式来存在
猫是个动物:单反满足is a 的表示都可以设置为继承
不理解对象的下面这个例子可以加上
分析:中午去饭馆吃饭,如何实现面向接口面层
接口是抽象的
菜单是一个接口 菜单是一个抽象的照片
谁面向接口调用 顾客面向菜单点菜
谁负责实现这个接口 厨师负责调用这个接口,做好某个菜
public interface FoodMenu {
void xihongshichaodan();
void yuxiangrousi();
}
public class ChineseCook implements FoodMenu {
@Override
public void xihongshichaodan() {
System.out.println("中餐厨师做的西红柿炒鸡蛋");
}
@Override
public void yuxiangrousi() {
System.out.println("中国厨师做的鱼香肉丝");
}
}
public class AmericCook implements FoodMenu{
@Override
public void xihongshichaodan() {
System.out.println("西餐厨师做的西红柿炒鸡蛋");
}
@Override
public void yuxiangrousi() {
System.out.println("西餐厨师做的鱼香肉丝");
}
}
import lombok.Data;
@Data
public class Customer {
private FoodMenu foodMenu;
/*这样就写死可,没有可插拔
ChineseCook aa;
AmericCook ac;
*/
public Customer() {
}
public Customer(FoodMenu foodMenu) {
this.foodMenu = foodMenu;
}
public void order(){
//FoodMenu fm= this.getFoodMenu();,
//或者直接使用
foodMenu.xihongshichaodan();//奔雷的直接使用
foodMenu.yuxiangrousi();
}
}
public class Test1 {
public static void main(String[] args) {
FoodMenu cook1 = new ChineseCook();
//Customer customer = new Customer(); //掉的是无参数的构造方法,导致Customer类的FoodMenu实例为空,,所以包空指针
Customer customer = new Customer(cook1);
customer.order();
//如果想要西餐的厨师
FoodMenu cook2 = new AmericCook();//这就是可插拔的,我把ChineseCook();换了,换成AmericCook()成可可插拔的
}
}
//当 Customer customer = new Customer(); //会出现空指针
只剩Customer,FoodMenu可以编译通过
Test1。ChineseCook,AmericCook也可以编译通过
类与类之间的关系
is a,has a, like a
is a: Cat is a Animal (猫是个动物)
但凡能满足is a 的表示继承关系
A extends B
hsa a:I has a pen (我有一只笔)
但凡能满足hsa a关系表示“”关联关系
关联关系通常以“属性的方式存在”
A {
B b;
}
like a
cook like a FoodMenu(厨师向一个)菜单一样
但凡能满足like 啊关系的表示“还实现类”
实现类关系通常是:类实现接口
A implements B
5、访问文控制权限
private int a; //私有的 只能在本类中访问
public int b; //公开的 在任何位置都可以访问
protected int weigth; //受保护的 只能在本类,,以及同包,可以访问
int d; // 默认 只能在本类以及同包下访问
临时补充输入的写
Scanner s = new Scanner(System.in);
String name= s.next();
System.out.println(name);
s.close();
6、Tostring
Tostring方法的目的是为了方便把java对象转化为String的方式表示
// 默认是继承object类,是不需要写的
public class Test03 extends Object{
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.println(s);
MyTime myTime = new MyTime(1970,1,1);
System.out.println(myTime);//输出引用的时候会默认调用tostring方法
System.out.println(myTime.toString());
}
}
@Data
class MyTime{
int year;
int month;
int day;
public MyTime() {
}
public MyTime(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public String toString(){
return this.year+"年"+this.month+"月"+""+this.day+"日";
}
}
7、euqals方法
1、判断两个对象不能用 “==”,==不能判断两个对象相等,所以每个类都要重写tostring和equals
public class Test03 extends Object{
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.println(s);
MyTime myTime = new MyTime(1970,1,1);
MyTime myTime1 = new MyTime(1970,1,1);
System.out.println(myTime==myTime1);//对比的是两个内存地址 false
System.out.println(myTime.equals(myTime1));//需要重写 true
}
}
@Data
class MyTime{
int year;
int month;
int day;
public MyTime() {
}
public MyTime(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public String toString(){
return this.year+"年"+this.month+"月"+""+this.day+"日";
}
}
instanceof 严格来说是Java中的一个双目运算符,用来测试一个对象是否为一个类的实例,用法为:https://www.cnblogs.com/ysocean/p/8486500.html
public boolean equals(Object obj) {
// 如果obj是一个空返回false
if(obj == null){
return false;
}
//如果obj不是一个mytime,没必要比较,直接饭后false
if(!(obj instanceof MyTime)){
return false;
}
if(this == obj){ // t1.euqals(t1)
return true;
}
//程序执行到此处,说明obj不是null,obj是mytime
MyTime t = (MyTime) obj;
if (this.year==t.year && this.month== t.month && this.day== t.day){
return true;
}
return false;
}
简写如下=====================
public boolean equals(Object obj) {
// 如果obj是一个空返回false,或者 //如果obj不是一个mytime,没必要比较,直接饭后false
if(obj == null || obj instanceof MyTime){
return false;
}
if(this == obj){ // t1.euqals(t1)
return true;
}
//程序执行到此处,说明obj不是null,obj是mytime
MyTime t = (MyTime) obj;
return this.year==t.year && this.month== t.month && this.day== t.day;
}
java中什么类型的数据可以使用 == 号判断
java中什么数据类型可以使用 equals 判断
当一个学生的学号相等,并且学校相同,表示同一个学生
finalize 方法
protected void finalize() throws Throwable{}
finalize 方法实际是哪个是sum公司为java程序员准备的一个实际,垃圾销毁实际
,如果希望在对象销毁实际执行一段代码,这段diamante要写到 finalize方法中
8、内部类和匿名内部类
匿名内内部类和lambda表达式主要的区别在于
1、匿名内部类他必须实现继承类的所有方法
2、匿名内部类在重写时有override标识,而lambda没有
3、lambda表达式继承的接口只能有一个抽血方法
在使用匿名内部类的过程中,我们需要注意如下几点:
1、使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能继承一个类或者实现一个接口。
2、匿名内部类中是不能定义构造函数的。
3、匿名内部类中不能存在任何的静态成员变量和静态方法。
4、匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效。
5、匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。
匿名内部类:在类的内部定义了一个新的类
内部类的分类:
静态内部类
实例内部类
局部内部类
实际上使用内部类编写代码,可读性太差
public interface Skill {
void use(); // 释放技能的抽象方法
}
public class SkillImpl implements Skill {
@Override
public void use() {
System.out.println("Biu~biu~biu~");
}
}
public class Hero {
private String name; // 英雄的名称
private Skill skill; // 英雄的技能
public Hero() {
}
public Hero(String name, Skill skill) {
this.name = name;
this.skill = skill;
}
public void attack() {
System.out.println("我叫" + name + ",开始施放技能:");
skill.use(); // 调用接口中的抽象方法
System.out.println("施放技能完成。");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Skill getSkill() {
return skill;
}
public void setSkill(Skill skill) {
this.skill = skill;
}
}
使用匿名对象或者匿名内部类来实现调用
public class DemoGame {
public static void main(String[] args) {
Hero hero = new Hero();
hero.setName("艾希"); // 设置英雄的名称
// 设置英雄技能
hero.setSkill(new SkillImpl()); // 使用单独定义的实现类
//还可以改成使用匿名内部类
Skill skill = new Skill() {
@Override
public void use() {
System.out.println("Pia~pia~pia~");
}
};
hero.setSkill(skill);
}
同时使用匿名内部类和匿名对象
// 进一步简化,同时使用匿名内部类和匿名对象
hero.setSkill(new Skill() {
@Override
public void use() {
System.out.println("Biu~Pia~Biu~Pia~");
}
});
hero.attack();
}
9、反射
反射的主要原理是通过字符方式去调用相应的常量和方法:eg,把方法名和变量名卸载.properties文件中
获取Class对象的方式:
1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
2. 类名.class:通过类名的属性class获取
3. 对象.getClass():getClass()方法在Object类中定义着。
Class对象功能:
* 获取功能:
1. 获取成员变量们
* Field[] getFields() 获取所有public修饰的成员变量
* Field getField(String name) 获取指定public修饰的成员变量
* Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符
* Field getDeclaredField(String name)
2. 获取构造方法们
* Constructor<?>[] getConstructors()
* Constructor<T> getConstructor(类<?>... parameterTypes)
* Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
* Constructor<?>[] getDeclaredConstructors()
3. 获取成员方法们:
* Method[] getMethods 获取所有public修饰的方法
* Method getMethod(String name, 类<?>... parameterTypes)
* Method[] getDeclaredMethods()
* Method getDeclaredMethod(String name, 类<?>... parameterTypes)
4. 获取类名
* String getName()
1. 获取成员变量们
Person.classs省略。。自己写
getFields()
public static void main(String[] args) throws Exception {
//0.获取Person的Class对象
Class personClass = Person.class;
//1.Field[] getFields()获取所有public修饰的成员变量
Field[] fields = personClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
getField()
//2.Field getField(String name)
Field a = personClass.getField("a");
//获取成员变量a 的值
Person p = new Person();
Object value = a.get(p);
System.out.println(value);
//设置a的值
a.set(p,"张三");
System.out.println(p);
getDeclaredFields() && getDeclaredField()
//Field[] getDeclaredFields():获取所有的成员变量,不考虑修饰符
Field[] declaredFields = personClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
//Field getDeclaredField(String name)
Field getd = personClass.getDeclaredField("d");
//忽略访问权限修饰符的安全检查
getd.setAccessible(true);//暴力反射
Object value2 = getd.get(p);//从p对象获取getd的值
System.out.println(value2);
2. 获取构造方法们
有参的构造器getConstructor(类<?>… parameterTypes)
public static void main(String[] args) throws Exception {
//0.获取Person的Class对象
Class personClass = Person.class;
//有参的构造器
//Constructor<T> getConstructor(类<?>... parameterTypes)
Constructor constructor = personClass.getConstructor(String.class, int.class);
//创建对象
Object person = constructor.newInstance("张三", 23);
System.out.println(person);
无参的构造器getConstructor()
//方式一
//无参的构造器
Constructor constructor1 = personClass.getConstructor();
System.out.println(constructor1);
//创建对象
Object person1 = constructor1.newInstance();
System.out.println(person1);
//方式二
//直接创建无参的构造器
Object o = personClass.newInstance();
System.out.println(o);
3. 获取成员方法们
获取无参的方法
public static void main(String[] args) throws Exception {
//0.获取Person的Class对象
Class personClass = Person.class;
//获取指定名称的方法
Method eat_method = personClass.getMethod("eat");
Person p = new Person();
//执行方法eat()方法
eat_method.invoke(p);
获取有参的方法getMethod()
//执行带一个String的犯法
Method eat_method2 = personClass.getMethod("eat", String.class);
//执行方法
eat_method2.invoke(p,"饭");
获取所有public修饰的方法:getMethods()
//获取所有public修饰的方法
Method[] methods = personClass.getMethods();
for (Method method : methods) {
System.out.println(method);
String name = method.getName();
System.out.println(name);
//method.setAccessible(true);
}
4. 获取类名
//获取类名
String className = personClass.getName();
System.out.println(className);//cn.itcast.domain.Person
测试反射,通Properties()对象来获取方法
pro.properties文件自己去创建
public class ReflectTest {
public static void main(String[] args) throws Exception {
//1.加载配置文件
//1.1创建Properties对象
Properties pro = new Properties();
//1.2加载配置文件,转换为一个集合
//1.2.1获取class目录下的配置文件
ClassLoader classLoader = ReflectTest.class.getClassLoader();
InputStream is = classLoader.getResourceAsStream("pro.properties");
pro.load(is);
//2.获取配置文件中定义的数据
String className = pro.getProperty("className");
String methodName = pro.getProperty("methodName");
//3.加载该类进内存
Class cls = Class.forName(className);
//4.创建对象
Object obj = cls.newInstance();
//5.获取方法对象
Method method = cls.getMethod(methodName);
//6.执行方法
method.invoke(obj);
}
}
10、函数式接口,一般配合Lambda表达式一起使用
(1)使用Lambda必须有接口,且接口只有一个抽象方法(即函数式接口)。
(2)Lambda必须可以“上下文推断”(就是依据语境推断出参数类型,这也是Lambda的一个优点,使得参数类型得以省略,更加简洁)
缺点:
(1)不容易debug模式调试;
(2)在lambda语句中强制类型转换不方便;
(3)不能再foreach中修改forEach外面的值
(4)如果不并行计算,很多时候计算速度不如传统for循环.
函数式接口:有且只有一个抽象方法的接口,称之为函数式接口
当然接口中可以包含其他的方法(默认,静态,私有)
@FunctionalInterface注解
作用:可以检测接口是否是一个函数式接口
是:编译成功
否:编译失败(接口中没有抽象方法抽象方法的个数多余1个)
@FunctionalInterface
public interface MyFunctionalInterface {
//定义一个抽象方法
public abstract void method();
}
public class MyFunctionalInterfaceImpl implements MyFunctionalInterface{
@Override
public void method() {
}
}
方法的参数是一个接口,所以我们可以传递接口的匿名内部类【匿名内部的作用就是减少实现类的编写】
public class Demo {
//定义一个方法,参数使用函数式接口MyFunctionalInterface
public static void show(MyFunctionalInterface myInter){
myInter.method();
}
public static void main(String[] args) {
//调用show方法,方法的参数是一个接口,所以可以传递接口的实现类对象
show(new MyFunctionalInterfaceImpl());
//调用show方法,方法的参数是一个接口,所以我们可以传递接口的匿名内部类
show(new MyFunctionalInterface() {
@Override
public void method() {
System.out.println("使用匿名内部类重写接口中的抽象方法");
}
});
}
}
使用Lambda表达式去重写method()方法【()代表的就是method()方法】
//调用show方法,方法的参数是一个函数式接口,所以我们可以Lambda表达式
show(()->{
System.out.println("使用Lambda表达式重写接口中的抽象方法");
});
//简化Lambda表达式
show(()-> System.out.println("使用Lambda表达式重写接口中的抽象方法"));
11、Stream的详细介绍
Stream的详细介绍所有的Collection集合都可以通过stream默认方法获取流;
https://blog.csdn.net/qq_41821963/article/details/125364126
public class Demo02Stream {
public static void main(String[] args) {
//创建一个List集合,存储姓名
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
//对list集合中的元素进行过滤,只要以张开头的元素,存储到一个新的集合中
//对listA集合进行过滤,只要姓名长度为3的人,存储到一个新集合中
//遍历listB集合
list.stream()
.filter(name->name.startsWith("张"))
.filter(name->name.length()==3)
.forEach(System.out::println);
}
}
把集合转换为Stream流
1、ArrayList集合中
public class Demo01GetStream {
public static void main(String[] args) {
//把集合转换为Stream流
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();
}
}
2、Set集合中
Set<String> set = new HashSet<>();
Stream<String> stream2 = set.stream();
3、键值对HashMap集合中key 和value的获取
Map<String,String> map = new HashMap<>();
//获取键,存储到一个Set集合中
Set<String> keySet = map.keySet();
Stream<String> stream3 = keySet.stream();
//获取值,存储到一个Collection集合中
Collection<String> values = map.values();
Stream<String> stream4 = values.stream();
4、获取键值对(键与值的映射关系 entrySet)
//获取键值对(键与值的映射关系 entrySet)
Set<Map.Entry<String, String>> entries = map.entrySet();
Stream<Map.Entry<String, String>> stream5 = entries.stream();
5、 把数组转换为Stream流
//把数组转换为Stream流
Stream<Integer> stream6 = Stream.of(1, 2, 3, 4, 5);
//可变参数可以传递数组
Integer[] arr = {1,2,3,4,5};
Stream<Integer> stream7 = Stream.of(arr);
String[] arr2 = {"a","bb","ccc"};
Stream<String> stream8 = Stream.of(arr2);
6、forEach
Stream流中的常用方法_forEach void forEach(Consumer<? super T> action); 该方法接收一个Consumer接口函数,会将每一个流元素交给该函数进行处理。 Consumer接口是一个消费型的函数式接口,可以传递Lambda表达式,消费数
据
public static void main(String[] args) {
//获取一个Stream流
Stream<String> stream1 = Stream.of("张三", "李四", "王五", "赵六", "田七");
//使用Stream流中的方法forEach对Stream流中的数据进行遍历
/*stream.forEach((String name)->{
System.out.println(name);
});*/
stream1.forEach(name->System.out.println(name));
}
7、filter
Stream流中的常用方法_filter:用于对Stream流中的数据进行过滤 Stream<T> filter(Predicate<? super T> predicate); filter方法的参数Predicate是一个函数式接口,所以可以传递Lambda表达式,对数据进行过滤 Predicate中的抽象方法: boolean test(T t);
Stream<String> stream = Stream.of("张三丰", "张翠山", "赵敏", "周芷若", "张无忌");
//对Stream流中的元素进行过滤,只要姓张的人
Stream<String> stream2 = stream.filter((String name)->{return name.startsWith("张");});
//遍历stream2流
stream2.forEach(name-> System.out.println(name));
7、map
Stream流中的常用方法_map:用于类型转换
如果需要将流中的元素映射到另一个流中,可以使用map方法.
Stream map(Function<? super T, ? extends R> mapper);
该接口需要一个Function函数式接口参数,可以将当前流中的T类型数据转换为另一种R类型的流。
Function中的抽象方法:
R apply(T t);
//获取一个String类型的Stream流
Stream<String> stream = Stream.of("1", "2", "3", "4");
//使用map方法,把字符串类型的整数,转换(映射)为Integer类型的整数
stream.map((String s)->{
return Integer.parseInt(s);
}).forEach((i-> System.out.println(i)));
//简写
stream.map(Integer::parseInt).forEach((System.out::println));
8、count
Stream流中的常用方法_count:用于统计Stream流中元素的个数 long count(); count方法是一个终结方法,返回值是一个long类型的整数 所以不能再继续调用Stream流中的其他方法了
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
list.add(7);
Stream<Integer> stream = list.stream();
long count = stream.count();
System.out.println(count);//7
9、limit
Stream流中的常用方法_limit:用于截取流中的元素 limit方法可以对流进行截取,只取用前n个。方法签名: Stream<T> limit(long maxSize); 参数是一个long型,如果集合当前长度大于参数则进行截取;否则不进行操作 limit方法是一个延迟方法,只是对流中的元素进行截取,返回的是一个新的流,所以可以继续调用Stream流中的其他方法
String[] arr = {"美羊羊","喜洋洋","懒洋洋","灰太狼","红太狼"};
Stream<String> stream = Stream.of(arr);
//使用limit对Stream流中的元素进行截取,只要前3个元素
Stream<String> stream2 = stream.limit(3);
//遍历stream2流
stream2.forEach(name-> System.out.println(name));
10、skip
Stream流中的常用方法_skip:用于跳过元素 如果希望跳过前几个元素,可以使用skip方法获取一个截取之后的新流: Stream<T> skip(long n); 如果流的当前长度大于n,则跳过前n个;否则将会得到一个长度为0的空流。
String[] arr = {"美羊羊","喜洋洋","懒洋洋","灰太狼","红太狼"};
Stream<String> stream = Stream.of(arr);
//使用skip方法跳过前3个元素
Stream<String> stream2 = stream.skip(3);
//遍历stream2流
stream2.forEach(name-> System.out.println(name));
11、concat
Stream流中的常用方法_concat:用于把流组合到一起
如果有两个流,希望合并成为一个流,那么可以使用Stream接口的静态方法concat static Stream
concat(Stream<? extends T> a, Stream<? extends T> b)
//创建一个Stream流
Stream<String> stream1 = Stream.of("张三丰", "张翠山", "赵敏", "周芷若", "张无忌");
//获取一个Stream流
String[] arr = {"美羊羊","喜洋洋","懒洋洋","灰太狼","红太狼"};
Stream<String> stream2 = Stream.of(arr);
//把以上两个流组合为一个流
Stream<String> concat = Stream.concat(stream1, stream2);
//遍历concat流
concat.forEach(name-> System.out.println(name));
练习:集合元素处理(Stream方式)
将上一题当中的传统for循环写法更换为Stream流式处理方式。
两个集合的初始内容不变,Person类的定义也不变。
public class Demo02StreamTest {
public static void main(String[] args) {
//第一支队伍
ArrayList<String> one = new ArrayList<>();
one.add("迪丽热巴");
one.add("宋远桥");
one.add("苏星河");
one.add("石破天");
one.add("石中玉");
one.add("老子");
one.add("庄子");
one.add("洪七公");
//1. 第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。
//2. 第一个队伍筛选之后只要前3个人;存储到一个新集合中。
Stream<String> oneStream = one.stream().filter(name -> name.length() == 3).limit(3);
//第二支队伍
ArrayList<String> two = new ArrayList<>();
two.add("古力娜扎");
two.add("张无忌");
two.add("赵丽颖");
two.add("张三丰");
two.add("尼古拉斯赵四");
two.add("张天爱");
two.add("张二狗");
//3. 第二个队伍只要姓张的成员姓名;存储到一个新集合中。
//4. 第二个队伍筛选之后不要前2个人;存储到一个新集合中。
Stream<String> twoStream = two.stream().filter(name -> name.startsWith("张")).skip(2);
//5. 将两个队伍合并为一个队伍;存储到一个新集合中。
//6. 根据姓名创建Person对象;存储到一个新集合中。
//7. 打印整个队伍的Person对象信息。
Stream.concat(oneStream,twoStream).map(name->new Person(name)).forEach(p-> System.out.println(p));
Stream.concat(oneStream,twoStream).map(Person::new).forEach(System.out::println);
}
}
输出:
Person{name=‘宋远桥’}
Person{name=‘苏星河’}
Person{name=‘石破天’}
Person{name=‘张天爱’}
Person{name=‘张二狗’}
六、数组
1、数组实际是一个容器,可以容纳多个元素
2、数组中可以储存基本数据类型,也可以储存引用数据类型
3、数组因为是引用数据类型,所以数组的对象储存在堆内存中
4、数组如果储存的是java对象,实际是哪个储存的是引用
5、数组一旦创建,在java中,长度不可变
6、java中数组要求数组中的元素的类型统一
数组的优点:
1,储存是连续的
2、每个元素的类型相同,空间大小相同
3、第一个元素的内存地址,就世道每个元素占用空间的大小
缺点:
1、在数组上随机增删的时候,会涉及到后面元素唯一
2、很难找一块大的连续的空间
7、数组的写法:
int[] array1;
boolean[] array2
String[] array3
Object[] array4
初始化一维数组的两种方式
静态初始化
int[] array ={1,2,3,4}
int array [] ={1,2,3,4}
动态初始化
int [] array1= new int[5] //初始化5个长度的数组元素
所以的数组都有length属性
修改:
遍历:
增加:
main方法中的String [] args 又什么作用//数组对象创建了,但数组中没有任何数据,
什么时候会有值,其实这个是留给用户的,主要是用来接收用户输入的参数
1、mian方法中 String[] args 解释
args参数的作用是获取系统输入的值
public static void main(String[] args) {
if(args.length != 2){
System.out.println("使用该系统请输入系统参数,例如张三 123");
}
String username= args[0];
String password=args[1];
if ("admin".equals(username)&& "123".equals(password)){
System.out.println("欢迎使用该系统");
}else {
System.out.println("登录失败");
}
}
2、一维数组
public static void main(String[] args) {
int [] array1= new int[5];
array1[0]=1; // 数组的复制,或者修改
array1[1]=3;
array1[2]=5;
array1[3]=7;
System.out.println(array1[0]);
//遍历数组
for (int i = 0; i < array1.length; i++) {
System.out.println(array1[i]);
}
}
]
1、数组为引用数据类型
public class Arraystest {
public static void main(String[] args) {
Annimeal a1= new Annimeal();
Annimeal a2= new Annimeal();
Annimeal [] Annimeals ={a1,a2};
for (int i = 0; i < Annimeals.length; i++) {
Annimeal a= Annimeals[i];
a.move();//数组中java对象的move的方法
}
}
}
class Annimeal{
public void move(){
System.out.println("动物在移动");
}
}
2、数组中存放对象。调用子类中的方法
package shuzu;
public class Arraystest {
public static void main(String[] args) {
Annimeal a1= new Annimeal();
Annimeal a2= new Annimeal();
Annimeal [] Annimeals ={a1,a2,new Cat(),new Brid()};
for (int i = 0; i < Annimeals.length; i++) {
Annimeal a= Annimeals[i];//取出来的数据还是要赋值给Annimeal数组
a.move();
}
}
}
class Annimeal{
public void move(){
System.out.println("动物在移动");
}
}
class Cat extends Annimeal {
public void move(){
System.out.println("猫抓老鼠");
}
}
class Brid extends Annimeal{
public void move(){
System.out.println("bird fly");
}
}
3、调用子类中特有的方法
/*
instanceof 严格来说是Java中的一个双目运算符,用来测试一个对象是否为一个类的实例,用法为
1:
boolean result = obj instanceof Class
其中 obj 为一个对象,Class 表示一个类或者一个接口,当 obj 为 Class 的对象,或者是其直接或间接子类,或者是其接口的实现类,结果result 都返回 true,否则返回false。
注意:编译器会检查 obj 是否能转换成右边的class类型,如果不能转换则直接报错,如果不能确定类型,则通过编译,具体看运行时定。
*/
package shuzu;
public class Arraystest {
public static void main(String[] args) {
Annimeal a1= new Annimeal();
Annimeal a2= new Annimeal();
Annimeal [] Annimeals ={a1,a2,new Cat(),new Brid()};
for (int i = 0; i < Annimeals.length; i++) {
//调用子类中特有的方法向下转型
if (Annimeals[i] instanceof Cat){
Cat cat = (Cat) Annimeals[i];//强制类型转换
cat.sing();
}else if(Annimeals[i] instanceof Brid){
Brid brid= (Brid) Annimeals[i];
brid.fly();
}
}
}
}
class Annimeal{
public void move(){
System.out.println("动物在移动");
}
}
class Cat extends Annimeal {
public void move(){
System.out.println("猫抓老鼠");
}
public void sing(){
System.out.println("猫在唱歌");
}
}
class Brid extends Annimeal{
public void move(){
System.out.println("bird fly");
}
public void fly(){
System.out.println("bird fly");
}
}
结果:
猫在唱歌
bird fly
以为数组的扩容
先新建一个大容量的数组,然后将小容量的数据拷贝进去,建议,基本数据类型和引用数据类型都可以拷贝
]
package shuzu;
public class Arryayscopy {
public static void main(String[] args) {
int [] src={1,2,3,4};
int [] dest=new int[20];
System.arraycopy(src,1,dest,2,2);
for (int i = 0; i < dest.length; i++) {
System.out.println(dest[i]);
}
}
}
结果
0
0
2
3
0
Process finished with exit code 0
3、 二维数组
package shuzu.erweishuzu;
/**
*
* 二位数组是一个特殊的以为数组,特殊在这个以为数组当中的每一个元素是一个一维数组
*
*/
public class Test09 {
public static void main(String[] args) {
//一维数组
int a1[]={1,2,3,4,5};
//二维数组
int a2[][]={{1,2,4,5,6},{3,4},{5,6}};
System.out.println("二维数组的长度"+a2.length);//说的是里面一维数组的个数 3
System.out.println("二位数组里面第一个一维数组的长度"+a2[0].length);//说的是里面一维数组的个数 5
for (int i = 0; i < a2.length; i++) {
//System.out.println(a2[i]);
for (int j = 0; j < a2[i].length; j++) {
System.out.println(a2[i][j]);
}
}
}
}
输出
二维数组的长度3
二位数组里面第一个一维数组的长度5
1
2
4
5
6
3
4
5
6
Process finished with exit code 0
动态初始化二维数组
int a3[][]=new int [2][4];
public class Test09 {
public static void main(String[] args) {
//二维数组
int a2[][] = {{1, 2, 4, 5, 6}, {3, 4}, {5, 6}};
printarray(a2);
//或者这样
printarray(new int[][]{{1, 2, 4, 5, 6}, {3, 4}, {5, 6}});
}
public static void printarray (int[][] a22){
for (int i = 0; i < a22.length; i++) {
//System.out.println(a2[i]);
for (int j = 0; j < a22[i].length; j++) {
System.out.println(a22[i][j]);
}
System.out.println();
}
}
}
1
2
4
5
6
3
4
5
6
Process finished with exit code 0
4、Arrays工具类
4.1、冒泡排序
4.2、二分法
4.3、选择排序
所有方法都是静态的
Arrays.binarySearch(a1,2);//查找该元素的下标
Arrays.sort(a1);//排序
自己去
import java.util.Arrays;这个类中找
String工具类
字符串在方法区中
package TestString;
/**
*
* String 表示字符串类型,属于引用数据类型,不属于基本数据类型
*
* 在java中四边使用双引号括起来的字符串都是String对象
* 在java中双引号括起来的对象都是不可变的
*
*/
public class Teststring {
public static void main(String[] args) {
String a1="djkdjf"+"adadfd";//创建了两个对象
System.out.println(a1);
//凡是双引号括起来的都是在字符串常量中有一份
//凡是new出来的对象都是在堆里面开辟空间
String a2= new String("abc");
}
}
public class Teststring {
public static void main(String[] args) {
方式一
String s1="hello";
String s2="hello";
System.out.println(s1==s2);//true
===============================================
方式二
String x=new String("xyz");
String y=new String("xyz");
System.out.println(x==y);//false
System.out.println("xyz".equals(x));//true
}
}
方式一的内存图
]
方式二的内存图
]
通过上面方法比较比较两个对象的值相等不能用-==号
5、关于string的常用构造方法
String的常用方法
public class StringTest01 {
public static void main(String[] args) {
byte[] bytes={97,98,99};
String s1= new String(bytes);
System.out.println(s1); //===abc
String s2= new String(bytes,0,2);//将byte中的一部分转换成字符串
System.out.println(s2); //====ab
char s3="中国人".charAt(1);
System.out.println(s3);// 输出:国
int result="abc".compareTo("abc");
System.out.println(result);//输出 0代表相等,<0的前小后大 ;>0的前大后效
System.out.println("abc".contains("a"));//前面的字符串是否包含后面 ture
System.out.println("test.java".endsWith(".java"));//判断以什么结尾 true
byte[] bytes1="abcdef".getBytes();//将字符串转换成字节数组
for (int i = 0; i < bytes1.length; i++) {
System.out.print(bytes1[i]+" ");//97 98 99 100 101 102
}
//判断某个字字符串第一次出现的索引
System.out.println("javajfhdfhadhfdhshfjdshfhdsfds".indexOf("java"));//0
//判断某个字符串是否为空
String s4="";
System.out.println(s4.isEmpty());
//判断字符串长度
System.out.println("abcd".length());//4
//替换字符串
String s5="http://www.baidu.com".replace("http://","https://");
System.out.println(s5);
//字符串的拆分
String[] ymr="1996-12.23".split("-");
for (int i = 0; i < ymr.length; i++) {
System.out.println(ymr[i]);//
1996
12
23
}
//从什么时候开始,从什么时候结束
String s6="http://www.baidu.com".substring(7,10);
System.out.println(s6);//输出:www
//将字符串转换成char数组
char[] CHAS="我是中国人".toCharArray();
for (int i = 0; i < CHAS.length; i++) {
System.out.print(CHAS[i]);//我是中国人
}
//转换小写
String s7= "ABCD".toLowerCase();
System.out.println(s8);//abcd
//转换大写
String s8= "abcd".toUpperCase();
System.out.println(s8);
//去除前后空白
System.out.println(" hello word ".trim());
//将不是字符串的转换成字符串eg:1.14
String s9 =String.valueOf(1.14);
System.out.println(s9);
}
}
得出结论,string方法重写了tosting方法
Stringbuffer
java中字符串是不可变的,每一次拼接都会产生新的字符串,这样会产生内存空间的浪费
String s10="";
for (int i = 0; i < 100; i++) {
s10=s10+i;
System.out.println(s10);
}
}
//底层实际是一个byte数组、不会创建新的数组
StringBuffer stringBuffer= new StringBuffer();
stringBuffer.append("a");
for (int i = 0; i < 100; i++) {
stringBuffer=stringBuffer.append(i);
System.out.println(stringBuffer);
}
每次都会产出新的字符串
]
6、8种包装类
package TestString;
import javax.jws.soap.SOAPBinding;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
public class StringTest01 {
public static void main(String[] args) {
//java中为8中基本数据类型准备了8种包装类,8种包装类是引用数据类型
//调用dosome()方法的时候需要穿一个数字
//但是dosome无法接收基本数据类型,那么可以穿一个数组对应的包装类
//把100经过构造方法经过包装成对象
myint my= new myint(100);
dosome(my);//把100经过构造方法经过包装成对象,没法直接传100
}
public static void dosome(Object obj){
System.out.println(obj); //输出100
}
}
//包装类
class myint{
int value;
public myint(){
}
public myint( int value){
this.value=value;
}
@Override
public String toString() {
return String.valueOf(value);
}
}
Interger ,Byte,Short,long,Float等
public class StringTest01 {
public static void main(String[] args) {
//java中为8中基本数据类型准备了8种包装类,8种包装类是引用数据类型
//调用dosome()方法的时候需要穿一个数字
//但是dosome无法接收基本数据类型,那么可以穿一个数组对应的包装类
//把100经过构造方法经过包装成对象
Integer my= new Integer(100);
dosome(my);//把100经过构造方法经过包装成对象
}
public static void dosome(Object obj){
System.out.println(obj);
}
}
public class StringTest01 {
public static void main(String[] args) {
//装箱
Integer i= new Integer(1);//将基本数据类型装成引用数据类型
System.out.println(i);
//拆箱
int val=i.intValue();//将引用数据类型转换成基本数据类型
System.out.println(val);
System.out.println(Integer.MAX_VALUE);// 获取最大值和自下肢
System.out.println(Integer.MIN_VALUE);
}
}
7、自动装箱和自动拆箱
public class StringTest01 {
public static void main(String[] args) {
装箱
Integer i =100;//自动装箱
拆箱
int b=i;//自动拆箱
}
}
String 中有一个byte数组,byte数组中有一个finaly,所以是不可变的
Internet中常用的放啊
Integer a1= new Integer(“熊磊”);//不能这样写,一定要是数组
package TestString;
import javax.jws.soap.SOAPBinding;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
public class StringTest01 {
public static void main(String[] args) {
Integer a1= new Integer("熊磊");
/**
*比较常见的异常
* 空指针异常
* 数据类型转换异常
* 数组下标越界异常
* *数字格式化异常 java.lang.NumberFormatException
*/
//将字符串的转换成int
int revalue= Integer.parseInt("133");
// String-->Integer
Integer A1= Integer.valueOf("100");
System.out.println(A1);
// int-->Integer
Integer a2= Integer.valueOf(100);
System.out.println(a2);
}
}
引用数据类型转换图
]
8、日期&数据处理
public class Date1 {
public static void main(String[] args) {
//日期转换成字符串
Date date=new Date();
SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd");//指定日期格式
String nowdate= dateFormat.format(date);//格式化
System.out.println(nowdate);
//字符串转换成日期格式
String time="2008-08-12";
SimpleDateFormat nowdate1= new SimpleDateFormat("yyy-MM-dd");
Date datetime= nowdate1.parse(time);
System.out.println(datetime);
//获取自从1970年到现在的毫秒数
long nowtime=System.currentTimeMillis();
System.out.println(nowtime);
System.gc();//垃圾回收器
//获取昨天的时间
Date time2= new Date(System.currentTimeMillis()-1000*60*60*24);
SimpleDateFormat dateFormat1= new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");//指定日期格式
String stri2=dateFormat1.format(time2);
System.out.println(stri2);
/*数组格式化
# 代表任意数字
, 代表千分位
. 代表小数点
0 不够使补0
*/
//DecimalFormat df= new DecimalFormat("数字格式化");
DecimalFormat df= new DecimalFormat("###,###.##");
String df1=df.format(12343434.56);
System.out.println(df1);
//BigDecimal的处理
BigDecimal v1= new BigDecimal(100);
System.out.println(v1);
BigDecimal v2= new BigDecimal(200);
System.out.println(v2);
//System.out.println(v1+v2); 引用不能直接相加
BigDecimal sum = v1.add(v2);
System.out.println(sum);
BigDecimal sum = v1.divide(v2,1,BigDecimal.ROUND_HALF_UP);
System.out.println(sum);
//产生一个int类型的
Random random= new Random();
int num1= random.nextInt();
System.out.println(num1);
//产生0-100之间的随机数
int num2= random.nextInt(101);
System.out.println(num2);
}
}
9、枚举
package date;
public class enumerate11 {
public static void main(String[] args) {
System.out.println(dive(1,2));
}
/**
* 计算int类型的数据商,计算成返回1,计算失败返回2
* @param a
* @param b
*/
//涉及上有什么问题,返回值类型会有问题,既然结果只是成功或者失败,正好可以返回bellone类型
public static int dive(int a,int b){
try {
int c=a/b;
return 1;
}catch (Exception e){
return 0;
}
}
}
//最好使用
public static boolean dive(int a,int b){
try {
int c=a/b;
return true;
}catch (Exception e){
return false;
}
}
结果只有结果只有 情况的话使用布尔类型多余两种的话使用枚举
package date;
public class enumerate11 {
public static void main(String[] args) {
System.out.println(dive(1,2));
}
/**
* 计算int类型的数据商,计算成返回1,计算失败返回2
* @param a
* @param b
*/
//涉及上有什么问题,返回值类型会有问题,既然结果只是成功或者失败,正好可以返回bellone类型
public static result dive(int a,int b){
try {
int c=a/b;
return result.SUCCESS;
}catch (Exception e){
return result.FIIL;
}
}
}
//枚举类型
enum result{
SUCCESS,FIIL
}
10、异常的处理
NumberFormatException a= new NumberFormatException("数据格式化异常");
NullPointerException b= new NullPointerException("空指正异常");
异常的处理方式
方法一:在在方法申明的时候使用throws 谁调用我我就抛给谁
方式二:使用try…catach 自己把这个钱给补上
/**
- 执行中发生了不正常的情况,
- 把改异常的信息打印出来
- 异常已类的形式存在,每个异常类都有一个异常对象,发生异常会穿件一个对象
*/
public class Excp01 {
public static void main(String[] args) {
dosome();//直接报错,需要捕捉异常
try{
dosome();
}catch (ClassNotFoundException e){
}
}
public static void dosome() throws ClassNotFoundException{
System.out.println("ddfd");
}
}
七、集合
集合详细解释
https://blog.csdn.net/feiyanaffection/article/details/81394745
https://www.runoob.com/java/java-collections.html
]
]
Collection接口中的方法
package 集合;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* 什么是集合,集合是一个容器,是一个载体,可以一次容纳多个对象
* 集合中任何时候储存都是一个引用
*
* 从上面的集合框架图可以看到,Java 集合框架主要包括两种类型的容器,
* 一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射。Collection
* 接口又有 3 种子类型,List、Set 和 Queue,再下面是一些抽象类,最后是具体实现类,
* 常用的有 ArrayList、LinkedList、HashSet、LinkedHashSet、HashMap、LinkedHashMap 等等。
*
*/
public class list {
/*
Collection中能存储什么元素
没使用泛型前只能存储作为object所有的子类
使用了泛型之后,Collection只能存储具体的类型
Collection常用方法
*/
public static void main(String[] args) {
//接口没办法穿件对象,父类型的引用指向了子类型的对象,引用多态
Collection s= new ArrayList() ;
s.add(199);//世界上是放进了一个形象的内存地址,之所以没有贬义报错是自动装箱
s.add(3.13);
s.add(new student());//放进一个对象
s.add("上海");
s.add("abc");
//或者集合的元素
System.out.println(s.size());
//s.clear();//清除元素
System.out.println(s.size());
//判断元素中是否包含199 包含返回true 否则false
System.out.println(s.contains(199));
//移除某个元素
System.out.println(s.remove(199));
//判断元素是否为空 是true 不是false
System.out.println(s.isEmpty());
//集合转换成数组
Object[] objects= s.toArray();
for (int i = 0; i < objects.length; i++) {
Object o = objects[i];
System.out.println(o);
}
}
}
class student{
}
5
5
true
true
false
3.13
集合.student@74a14482
上海
abc
迭代器:
package 集合;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
public class colletcions {
public static void main(String[] args) {
/*
关于集合的遍历迭代
*/
Collection a = new HashSet();
a.add("abc");
a.add(123);
a.add("类");
//第一步,获取获取集合对象的迭代器对象
Iterator it = a.iterator();
while (it.hasNext()) {
//下面两句可以省略,用于测试
Boolean aa = it.hasNext();
System.out.println(aa);//是不是有下一个,有true,没有false
Object Obj = it.next();
System.out.println(Obj);
}
}
}
contains,remove详解
package 集合;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
public class colletcions {
public static void main(String[] args) {
/*
关于集合的遍历迭代
*/
Collection a = new ArrayList();
String s1= new String("123");
a.add(s1);
String s2= new String("456");
a.add(s2);
String s3= new String("789");
a.add(s3);
String s4= new String("123");
System.out.println(a.contains(s4));//a集合中是否包含123
System.out.println(a.remove(s4));
}
}
List 中特有的方法
package 集合;
import java.util.ArrayList;
import java.util.List;
public class LISTS {
public static void main(String[] args) {
List arrayList= new ArrayList();
arrayList.add(10);
arrayList.add(1,"1");//指定下标插图元素
for (int i = 0; i < arrayList.size(); i++) {
System.out.println(arrayList.get(i));
}
//增强for循环
for (Object L:arrayList) {
System.out.println(L);
}
//第一次出现与元素的下标
System.out.println("第一次出现与元素的下标:"+arrayList.indexOf(10));
//下标为0的匀速修改为20
arrayList.set(0,20);
}
}
泛型的定义
package 集合;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class LISTS {
public static void main(String[] args) {
List mylist= new ArrayList();
Cat c= new Cat();
Dog b= new Dog();
mylist.add(c);
mylist.add(b);
//只在编译器阶段起作用,好处是存储的匀速类型统一,不需要大量的强制类型转换,导致集合中的元素缺乏多样性
Iterator<Animail> it=mylist.iterator();
while (it.hasNext()){
Animail ab= it.next();
ab.move();
}
}
}
class Animail {
public void move(){
System.out.println("动物在移动");
}
}
class Cat extends Animail{
public void move(){
System.out.println("cat在移动");
}
}
class Dog extends Animail{
public void move() {
System.out.println("dog在移动");
}
//这个个在子类中特有的方法
public void dogcat(){
}
}
package 集合;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class fanx {
public static void main(String[] args) {
List<String> a= new ArrayList<>();
a.add("www.baidu.com");
a.add("www.aiqiyi.com");
Iterator<String> it= a.iterator();
while (it.hasNext()){
//如果没有使用泛型返回会是个objec,之后还要转换
String b= it.next();
String bb= b.substring(7);
System.out.println(bb);
}
}
}
Hashset
package 集合;
//存储进去和输出的顺序不一趟
import java.util.HashSet;
import java.util.Set;
public class sets {
public static void main(String[] args) {
Set<String> str= new HashSet<>();
str.add("1");
str.add("2");
str.add("3");
str.add("4");
str.add("5");
str.add("6");
for (String a: str) {
System.out.println(a);
}
}
}
map
package 集合;
import java.awt.image.ImageProducer;
import java.util.*;
public class sets {
public static void main(String[] args) {
/*
Map和 colletcion没有任何关系
key和value都是引用数据类型
key和vlalue存储的都是内存地址
map中常用的接口
put
getcleat
isEmply
set
size
remover
*/
Map<Integer,String> map= new HashMap<>();
map.put(1,"上海");
map.put(2,"北京");
String v1=map.get(1);
System.out.println(v1);
System.out.println("键值对的个数:"+map.size());
map.remove(1);
System.out.println("键值对的个数:"+map.size());
//是否存在key1
System.out.println(map.containsKey(2));
//是否存在value 上海
System.out.println(map.containsValue("北京"));
//判断是否为空
System.out.println(map.isEmpty());
=============================================
//获取所有的value
Collection<String> values= map.values();
for (String ab:values) {
System.out.println(ab);
}
====================================
//遍历key,通过key获取value
//获取都有的key,所有的key都是value集合
Set<Integer> keys= map.keySet();
//遍历key,统计故宫key获取value
Iterator<Integer> it= keys.iterator();
while (it.hasNext()){
Integer key= it.next();
String value=map.get(key);
System.out.println(key+"="+value);
}
//第二种方法
for (Integer key:keys) {
System.out.println(key+"="+map.get(key));
}
//第三种方法
Set<Map.Entry<Integer,String>> set= map.entrySet();
Iterator<Map.Entry<Integer,String>> it1= set.iterator();
while (it1.hasNext()){
Map.Entry<Integer,String> node= it1.next();
System.out.println();
Integer key= node.getKey();
String value=node.getValue();
System.out.println(key+"="+value);
}
//第三种。把map集合直接转换成set集合
Set<Map.Entry<Integer,String>> set= map.entrySet();
Iterator<Map.Entry<Integer,String>> it1= set.iterator();
while (it1.hasNext()){
Map.Entry<Integer,String> node= it1.next();
System.out.println();
Integer key= node.getKey();
String value=node.getValue();
System.out.println(key+"="+value);
}
}
}
上海
键值对的个数:2
键值对的个数:1
true
true
false
北京
2=北京
2=北京
2=北京
public static void main(String[] args) {
//接口没办法穿件对象,父类型的引用指向了子类型的对象,引用多态
//ArrayList不是栈城安全的
ArrayList s= new ArrayList() ;
s.add(199);//世界上是放进了一个形象的内存地址,之所以没有贬义报错是自动装箱
s.add(3.13);
s.add(new student());//放进一个对象
s.add("上海");
s.add("abc");
//变成线程安全的
Collections.synchronizedList(s);
//排序
Collections.sort(s);
================================================================
//将set集合转换成list集合
Set<String> set= new HashSet<>() ;
set.add("199");//世界上是放进了一个形象的内存地址,之所以没有贬义报错是自动装箱
set.add("3.13");
set.add("上海");
set.add("abc");
//set集合不能调用sort,只能将set集合转换成list集合
List<String> mylist=new ArrayList<>(set);
Collections.sort(mylist);
}
IO流
什么是IO流
文件的读写
通过Io可以完成文件的读和写
这种流使能读取文本文件,不能读取声音,图片,视频,word等文件
分类:
输出流,输入流
字节流,字符流
java中的流都已经写好了
java中提供了那些流
https://www.cnblogs.com/shuaiguoguo/p/8883862.html
Vimport java.io.*;
public class IO流 {
/*
什么是IO流
文件的读写
通过Io可以完成文件的读和写
这种流使能读取文本文件,不能读取声音,图片,视频,word等文件
分类:
输出流,输入流
字节流,字符流
java中的流都已经写好了
java中提供了那些流
*/
public static void main(String[] args) throws IOException {
//.FileInputStream
InputStream inputStream = new FileInputStream(new File("D://hello//test.txt"));
int i = 0;
//一次读取一个字节
while ((i = inputStream.read()) != -1) {
// System.out.print(i + " ");// 65 66 67 68
//为什么会输出65 66 67 68?因为字符在底层存储的时候就是存储的数值。即字符对应的ASCII码。
System.out.print((char) i + " ");// A B C D
}
//关闭IO流
inputStream.close();
//.FileOutputStream
OutputStream outputStream = new FileOutputStream(new File("D://hello//test.txt"));
// 写出数据
outputStream.write("ABCD".getBytes());
// 关闭IO流
outputStream.close();
// 内容追加写入
OutputStream outputStream2 = new FileOutputStream("D://hello//test.txt", true);
// 输出换行符
outputStream2.write("\r\n".getBytes());
// 输出追加内容
outputStream2.write("hello".getBytes());
// 关闭IO流
outputStream2.close();
}
}
序列化
常用工具的处理
JSON.parseObject和JSON.toJSONString
JSON.parseObject 是将Json字符串转化为相应的对象;
JSON.toJSONString 是将对象转化为Json字符串
两者主要用于前后台的数据传输过程中
public class Test01 {
private static class Obj1 {
private String School;
private List<String> studen;
public List<String> getStuden() {
return studen;
}
public void setStuden(List<String> studen) {
this.studen = studen;
}
public String getSchool() {
return School;
}
public void setSchool(String school) {
School = school;
}
}
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("studens","{\"city\":{\"School\":\"san\",\"studen\":[1,2,3]}}");
Map<String, Obj1> student = JSON.parseObject(map.get("studens"), new TypeReference<Map<String,Obj1>>(){});
System.out.println(student);
Set<Map.Entry<String,Obj1>> entries=student.entrySet();
for(Map.Entry<String,Obj1> aa:entries){
System.out.println(aa);
Obj1 value=aa.getValue();
String school=value.getSchool();
System.out.println(school);
List<String> studet=value.getStuden();
System.out.println(studet);
}
}
}
StringUtils.isBlank(a)
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("studens","{\"city\":{\"School\":\"san\",\"studen\":[1,2,3]}}");
map.put("a","1");
map.put("b","2");
String a=map.get("studens");
Boolean as=StringUtils.isBlank(a)? Boolean.valueOf(map.get("a")) :Boolean.valueOf(map.get("a"))&&Boolean.valueOf(map.get("b"));
}
Arrays.asList
public static void main(String[] args) {
AlertRule alertRule= JSON.parseObject("{\"diffAbs\":{\"upper\":2000,\"lower\":23000},\"diffPercent\":{\"upper\":2000,\"lower\":23000},\"relation\":\"OR\"}",AlertRule.class);
System.out.println(alertRule.getDiffAbs());
String a="1,2,3,4,5,6";
List<String> list= Arrays.asList(a);
System.out.println(list);
}
常用的排序和计算和的方法
public class TestSort {
public static void main(String[] args) {
int[] arry1={2,4,5,6,7,2,2,4,6,8,9};
int temp=0;
for (int i = 0; i < arry1.length; i++) {
for(int j=0;j<arry1.length-1-i;j++){
if(arry1[j]>arry1[j+1]){
temp=arry1[j];
arry1[j]=arry1[j+1];
arry1[j+1]=temp;
}
}
}
System.out.println(Arrays.toString(arry1));
int[] arry2={2,4,5,6,7,2,2,4,6,8,9};
Arrays.sort(arry2);
System.out.println(arry2);
int[] arry3={2,4,5,6,7,2,2,4,6,8,9};
int max=arry3[0];
for (int i = 1; i < arry3.length; i++) {
if(arry3[i]>max){
max=arry3[i];
}
}
System.out.println(max);
//求和的4中方式
int sum1=0;
for (int i = 0; i <= 10; i++) {
sum1+=i;
}
System.out.println(sum1);
int[] sum2={2,4,5,6,7,2,2,4,6,8,9};
int sum2s=0;
for (int i : sum2) {
sum2s+=i;
}
System.out.println(sum2s);
int sum3=0;
int i=0;
do{
sum3=sum3=i;
i++;
}while (i<=10);
System.out.println(sum3);
int sum4=0;
int j=1;
while (j<=10){
sum4+=j;
j++;
}
System.out.println(sum4);
//1-100之間偶數和
int sum5 = 0;
for (int a = 1;a <= 100;a++) {
if (a % 2 == 0) {
sum5 += a;
}
}
System.out.println("结果是: " + sum5);
for(int b=2;b<=100;b++){
boolean flag=true;
for(int d=2;d<b;d++){
if(b%d==0){
flag=false;
break;
}
}
if(flag==true){
System.out.print(b+" ");
}
}
}
}
常用的日期处理方式
public class TimeUtls {
//判断选择的日期是否是今天
public static boolean isToday(long time) {
return isThisTime(time, "yyyy-MM-dd");
}
//判断选择的日期是否是本周
public static boolean isThisWeek(long time) {
Calendar calendar = Calendar.getInstance();
int currentWeek = calendar.get(Calendar.WEEK_OF_YEAR);
calendar.setTime(new Date(time));
int paramWeek = calendar.get(Calendar.WEEK_OF_YEAR);
if (paramWeek == currentWeek) {
return true;
}
return false;
}
//判断选择的日期是否是本月
public static boolean isThisMonth(long time) {
return isThisTime(time, "yyyy-MM");
}
public static boolean isThisTime(long time, String pattern) {
Date date = new Date(time);
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
String param = sdf.format(date);//参数时间
String now = sdf.format(new Date());//当前时间
if (param.equals(now)) {
return true;
}
return false;
}
@Test
public void testTime() {
isToday(1416360654000L);
isThisMonth(1416360654000L);
isThisWeek(1416360654000L);
}
}