一、标识符:
标识符就是指在程序中,我们自己定义的内容。
比如类名,变量名,方法名等等。
命名规则:(必须遵守)
1,不能数字开头
2,不能是java中的关键字和保留字
3,可以包含数字,字母(区分大小写),$和_
命名规范:(行内要求)
1,类名:首字母大写,后面每个单词首字母大写(大驼峰)
类名必须与文件名一致
2,变量名:首字母小写,后面每个单词首字母大写(小驼峰)
3,方法名:与变量名相同
推荐:尽量做到见名知意
二、八大基本类型
整数型:
byte:所占字节:1 所占位数:8
short:所占字节:2 所占位数:16
int:所占字节:4 所占位数:32
long:所占字节:8 所占位数:64;推荐 long 类型结尾加大写L
存储范围:byte(-128到127) (-(2的n-1次方)~(2的n-1次方)-1) n为所占位数 默认值是0
浮点型:
float:float 所占字节:4 所占位数:32 必须结尾加大写F或f,小数默认是float类型
double:double 所占字节:8 所占位数:64
默认值是 0.0
字符型:
char:char 所占字节:2 所占位数:16
必须单引号包裹,并且只能写一个字母
默认值:\u0000
布尔型:
boolean:boolean 所占字节:1 所占位数:8
默认值false
三、类型转换
自动转换:
小转大,小类型往大类型提升,随便用
float==》long 不允许,因为大类型不一致
long==》float 允许,可能数据溢出,精度丢失
强制转换:
long==》short 需要强制类型转换
long myLong = 10000L;
short myShort = (short)myLong;
char 底层使用 阿斯克码 只要值匹配 阿斯克码就会自动转换
int 类型的值,只要满足 char 范围会隐式强制转换
强制转换注意事项:
注意:在java中数字类型常量会有默认类型
整数默认类型:int
浮点数默认类型:double
注意!!!定义 byte 和 short时,
右侧常量如果没有超过其定义范围会隐式强制转换成左侧类型
常量:在程序运行过程中不会发生改变的值
byte myByte2 = 64;// byte myByte2 = (byte)100;
强制转换:需要谨慎使用,可能造成精度丢失,数据溢出
short myShort2 = 200;
byte/short/char 进行运算过程时自动转型成 int
int myInt2 = myByte2+myShort2;
总结:
1,强制转换需要谨慎使用,因为有可能发生数据溢出,精度丢失
2,byte/short/char 这三种类型会转换成 int 类型进行数字运算
3,boolean 不能进行任何数据类型转换
4,如果右侧都是常量运算并且结果没有大于左侧范围会隐式强转
如果右侧存在变量运算那么不会隐式强转
四、运算符号
java运算符号:
算术运算符号:+ - * / % ++ –
如果整形运算结果必定整形
如果运算中有浮点类型结果必定是浮点类型
小范围和大范围进行运算结果会自动提升至大范围
赋值运算符号:= += -= *= /=
符号左侧只能使用变量!
会帮我们隐式强转,不论值是否超出范围
int+=long; ==》 int = (int)(int + long);
比较运算符号:> < >= <= ,!= ==
结果必定是 boolean 类型,符号两次必须为数值类型(char可以)
!= 和 ==,会比较其字面值是否相等,所有类型都可以
逻辑运算符号: 或|| 与&& 非!
单独使用时 & 和 | 做的是运算
如果两侧为boolean 时
与符号两侧为true则为true
或符号两侧有一个为true则为true
注意:&& 和 || 有短路的作用
&& 如果左侧为 false 右侧不执行
|| 如果左侧为 true 右侧不执行
++ 和 –
符号使用必须为变量
a++:++ 在后,先操作再运算
++a:++ 在前,先运算后操作
拓展:三元运算
判断关系式 ? 操作1(true):操作2(false)
==和equals的区别?
https://blog.csdn.net/qq_42674061/article/details/109737235
五、常用类及其包含方法
1.Scanner
扫描类,可以扫描指定位置的内容。我们可以借助扫描类让用户使用控制台交互
.next() 获取控制台输入的字符串 返回String
.nextInt() 获取输入的整数,返回int
2.Math
Math类是final类,并且它的所有成员变量和成员方法都是静态的。
Math.random() 返回 [0,1) 随机小数,包括0 不包括1
3.System
System.out.println() 输出字符串
system.currentTimeMills 获取当前时间,返回long类型
4.Object
https://blog.csdn.net/qq_42674061/article/details/113806482
5.String
https://blog.csdn.net/qq_42674061/article/details/113806482
6.Date
日期类
7.SimpleDateFormate
(1).String转换为Date:
String strDate = "yyyy-MM-dd" ;
//创建SimpleDateFormat类对象
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd") ;
//注意 :simpleDateFormat在解析文本格式的时候,里面 模式(规则)一定要和文本格式的模式一直,否则就出现PareseException
Date dd = XXX.parse(strDate) ;
(2).Date转换为String:
Date d = new Date() ;
//创建SimpleDateFormat类对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String str = sdf.format(d) ;
8.Calendar
获取当前主机时间
Calendar cal = Calendar.getInstance();
// 如果想设置为某个日期,可以一次设置年月日时分秒,由于月份下标从0开始赋值月份要-1
// cal.set(year, month, date, hourOfDay, minute, second);
cal.set(2018, 1, 15, 23, 59, 59);
// 或者6个字段分别进行设置,由于月份下标从0开始赋值月份要-1
cal.set(Calendar.YEAR, 2018);
cal.set(Calendar.MONTH, Calendar.FEBRUARY);
cal.set(Calendar.DAY_OF_MONTH, 15);
cal.set(Calendar.HOUR_OF_DAY, 23);
cal.set(Calendar.MINUTE, 59);
cal.set(Calendar.SECOND, 59);
System.out.println(cal.getTime());
七、结构语句
1.顺序结构:
2.选择结构:
多个 if 和 多个 else if 区别:
多个 if 会逐个判断,只要满足就会执行其中代码
多个 else if 因为是一个整体,所以当其中一个满足时后续不执行
3.循环结构:
循环中的关键字:
break:退出当前循环,后续代码不执行
continue:跳出本次循环,后续代码本次循环不执行
4.总结:
如果已知循环次数,推荐使用for循环
如果循环次数未知,推荐使用while循环
单纯的执行效率而言 while 远远高于 for
八、数组
1.数组特点:(Array)
存储一系列值的容器,必须相同数据类型,长度固定。
特点:1,数组是引用类型
2,数组中所有数据的类型必须一致
3,数组的长度在运行期间不可改变
2.创建数组的方式:
//第一种:数据类型[] 变量名 = new 数据类型[长度];
int[] arrayOne = new int[10];
//第二种:数据类型[] 变量名名 = {元素,元素,元素};
int[] arrayTwo = {1,2,4,8,9};
//第三种:数据类型[] 变量名 = new 数据类型[]{元素,元素...};
int[] arrayThree = new int[]{4,8,7,6};
3.数组排序:
①冒泡排序:
for (int i = 0; i < arr.length - 1; i++) {
// 通过冒泡 每一次找出一个最值
for (int j = 0; j < arr.length - 1 - i; j++) {
if(arr[j]>arr[j+1]){
// 位置互换
cup = arr[j];
arr[j] = arr[j+1];
arr[j+1] = cup;
}
}
System.out.println("第"+(i+1)+"次:"+Arrays.toString(arr));
}
②选择排序:
//在数组中选择性的找出最值,放置到数组的指定位置
//然后再在未操作的元素中重复以上操作
// 找最值 最大值
// 定义一个杯子
int cup;
for (int i = 1; i < arr.length; i++) {
// 存储最值下标
int max = arr.length - i;
// 通过该循环找出最值
for (int j = 0; j < arr.length - i; j++) {
if(arr[max]<arr[j]){
// 改变 杯子中存储的下标
max = j;
}
}
// 进行元素的位置互换 arr[max] arr[arr.length-i]
cup = arr[max];
arr[max] = arr[arr.length-i];
arr[arr.length-i] = cup;
System.out.println("第"+i+"次:"+ Arrays.toString(arr));
}
③反转排序:
//把数组中的元素顺序反转 {1,2,3,4,5}--->{5,4,3,2,1}
int cup;
for (int i = 0; i < arr.length/2; i++) {
//位置互换
// arr[i] <==> arr[arr.length-i-1]
cup = arr[i];
arr[i] = arr[arr.length-i-1];
arr[arr.length-i-1] = cup;
}
④插入排序:
//把数组切割成两部分,一部分为有序的,一部分为无序
//每一次都从无序部分获取一个元素,插入至有序部分
//使有序部分每一次都成为一个新的有序数组
{33, 52, 68, 16, 92, 73, 29}
// 空杯子
int cup;
for (int i = 1; i < arr.length; i++) {
for (int j = i; j > 0; j--) {
if(arr[j]<arr[j-1]){
cup = arr[j];
arr[j] = arr[j-1];
arr[j-1] = cup;
}
}
}
⑤快速排序:
// 通过别人帮我写好的直接使用
//Arrays.sort(arr);
// 可以指定位置排序 [fromIndex,toIndex)
Arrays.sort(arr,1,4);
System.out.println(Arrays.toString(arr));
4.数组常用的属性:
.length 获取数组长度
5.数组常用方法:
indexOf() 返回当前元素在数组中的索引
sort() 返回排序好的数组
push() 将元素添加至数组末尾
pop() 删除并返回数组最后一个元素
concat() 连接多个数组,返回一个新数组
reverse() 颠倒数组元素顺序
//查看数组中是否包含某个元素:转换为string(toString())或集合调用contains()方法
Arrays.asList():转化为list
//合并数组:先将两数组asList变为list,再用第三个集合addAll()这两个的集合,最后用toArray()将集合变为数组
九、集合
集合的底层是数组 ,动态扩增: Arrays.copyOf()
十、I/O流
十一、socket
b/s browser浏览器/server服务器, 通俗的讲就是网站
b/s架构的程序底层是通过http协议通信
c/s client客户端/server服务器,端游,手游,客户端需要安装
socket技术是c/s架构的程序 底层 通信的技术手段。
socket技术是2台不同IP主机之间通信的技术方法。
端口:是操作系统开放给应用程序给外界通信的门,每个操作系统有65535个门
端口默认是关闭状态,应用程序想要别人来发送数据,需要先监听一个门
socket服务端编写步骤:
1:创建ServerSocket对象,创建对象的同时,设置当前操作系统你要监听的IP及端口 ServerSocket ser=new ServerSocket(8999);
2:等待客户端连接 accept(),accept会阻塞等待客户端的连接,如果连接来了,会返回一个Socket 代表客户端信息的对象
Socket sa=ser.accept();
3.先读客户端信息,InputStream in=sa.getInputStream();DataInputStream dis=new DataInputStream(in);
4.再写服务器端信息,OutputStream os=sa.getOutputStream();DataOutputStream dos=new DataOutputStream(os);
5.关闭流
socket客户端编写步骤:
1:创建一个Socket对象,同时告诉Socket对象你要连接的服务器IP及端口,创建Socket对象的同时就会去连接服务器
Socket sa=new Socket(“localhost”,8999);
2.//客户端先输出信息
OutputStream os=sa.getOutputStream();
DataOutputStream dos=new DataOutputStream(os);
3. //客户端等下还要读信息
InputStream in=sa.getInputStream();
DataInputStream dis=new DataInputStream(in);
实例代码:
//客户端:
public class ClientA {
public static void main(String[] args) throws IOException {
Socket sa=new Socket("localhost",8999);
//客户端先输出信息
OutputStream os=sa.getOutputStream();
DataOutputStream dos=new DataOutputStream(os);
//客户端要输出信息,得先从控制台
Scanner sc=new Scanner(System.in);
//客户端等下还要读信息
InputStream in=sa.getInputStream();
DataInputStream dis=new DataInputStream(in);
String info;
while(true){
System.out.println("客户端说:");
info=sc.nextLine();
dos.writeUTF(info);
if(info.equals("bye")){
break;
}
//读信息
info=dis.readUTF();
System.out.println("服务器端说"+info);
if(info.equals("bye")){
break;
}
}
dis.close();
dos.close();
}
}
//服务器端
public class ServerA {
public static void main(String[] args) throws IOException {
//创建服务器对象
ServerSocket ser=new ServerSocket(8999);
Socket sa=ser.accept();//等待客户端请求
//先读客户端信息,通过客户端的方法调用
InputStream in=sa.getInputStream();
DataInputStream dis=new DataInputStream(in);//数据流
//服务器收到信息后,发出信息
OutputStream os=sa.getOutputStream();
DataOutputStream dos=new DataOutputStream(os);
//要发出信息,从控制台中 发出
Scanner sc=new Scanner(System.in);
String info;//等下要用于显示
while (true){//一直进行
//先读
info= dis.readUTF();
System.out.println("客户端说"+info);
if(info.equals("bye")){
break;
}
System.out.println("服务器说:");
info=sc.nextLine();
dos.writeUTF(info);
if(info.equals("bye")){
break;
}
}
dis.close();
dos.close();
}
}
十二、设计模式
十三、多线程
2.sleep和wait的区别?
1,这两个方法来自不同的类分别是Thread和Object
2,最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
3,wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用
4,sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常
3.程序、进程、线程的关系?
程序:是一段静态的代码,是应用软件执行的蓝本。
进程:是程序一次动态执行的过程,它对应了从代码加载、执行完毕的一个完整过程,这也是进程开始到消亡的过程。
线程:是进程中独立、可调度的执行单元,是执行中最小单位。
一个程序一般是一个进程,但可以一个程序中有多个进程,一个进程中可以有多个线程,但只有一个主线程。
Java应用程序中默认的主线程是main方法,如果main方法中创建了其他线程,JVM就会执行其他的线程。
十四、反射
1.什么是反射?
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
十五、序列化和反序列化
1.序列化:
把java中内存中的对象 用一种特殊的数据格式永久的保存在文件中
如何把一个对象在网络中传输?先把对象序列化成二进制数据,
然后在网络中用tcp/ip协议传输
实现序列化的步骤:
1:让要序列化的类实现Serializable接口
2:用io序列化
序列化的一些注意事项:
1:序列化和反序列化 对象版本要一致(属性名,属性个数等等都要一致)
2:要序列化多个对象用一个ObjectOutputStream对象writeObject多次即可
或者把多个对象放入list等集合对象中再writeObject一次即可readObject反序列化得到的对象也是集合对象
3:一定要在多个ObjectOutputStream对象中写多个对象情况怎么反序列化?
文件追加模式时会默认加4个字节的换行符 字符,这样反序列化会失败。
反序列化
把序列化后的二进制数据 转换成java中的对象
十六、内部类
为什么要使用内部类?好处?
所以你可以认为内部类提供了某种进入其外围类的窗口。
使用内部类最吸引人的原因是:每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了“多重继承”。
1 成员内部类: 内部类中,不准有任何static 变量或static方法.
希望内部类类似于一个实例变量.每new一份,都会有新的属性值.
2 静态内部类:
如果希望内部类中有static变量或static方法,此内部类要定义为static
静态内部类和成员内部类:
2.1 此静态内部类,不须实例化.
直接可通过外部类.调用
2.2 静态内部类内部可含有static和非static属性 方法.
2.3 静态内部类,不能再用外面的非静态属性或方法
3 方法内部类:定义在方法里的类。
因为这个类是在方法内,只在此方法内有效果,不须加public private protected 控制符.
除了此方法能调用此类外,其它地方调用不了此类.
适用场景:
封装信息,别处须通过此方法得到足够的信息.
此内部类中的方法参数:参数可以有,参数就默认为final
4 匿名内部类:
就是一个没有名字的方法内部类.要和方法结合使用.
大致结构是参考方法内部类,只是没有类名,代码块还在.
4.1 匿名内部类须先继承一个抽象类或实现一个接口
4.2 因为没有类名,所以没有构造器.
适合场景:懒汉式实现接口或继承抽象类.