本文章只写每个知识点的例句,想了解具体的,请到JavaSE目录查看
javaSE阶段各知识点
一、环境配置
1 JDK环境变量path配置作用:
配置后可以在任意目录下运行javac和java命令,让DOS窗口可以在任意路径下编译和运行java文件,如果不配置只能在bin目录下运行
2 JDK,JRE,JVM的特点:
JVM:用来运行Java程序的底层虚拟机,在软件工具中运行的时候就是使用的JVM虚拟机。可以使java程序实现跨平台(java程序实现跨平台的最根本原因:在不同的操作系统上安装不通过的JVM)
JRE:java程序的运行环境,包含了JVM和一些核心类库
JDK:java程序的开发环境。包含了JRE和开发工具包
结论:JDK=JRE(JRE=JVM+核心类库)+工具包
3 path和classpath环境变量的作用:
path:可以让一些可以执行程序(命令)在任意的DOS目录下都可以正常的执行。在java中可以使用javac命令和java命令在任意的目录下执行编译和运行的操作
classpath:
- 用来设置java命令的所要执行的.class文件的存放路径。
- 在操作系统中设置了classpath后,JVM只会去执行classpath环境变量中所配置的.class文件存放目录下的class文件
- 操作系统中没有设置classpath,JVM也会去先找classpath环境变量,因为classpath不存在,所以会再去当前目录下的找到相应的.class文件
4 DOS窗口常用命令
命令 | 描述 |
---|---|
cd \ | 进入到根目录 |
cd 文件夹名 | 进入指定文件夹 |
d: | 进入到D盘 |
dir | 遍历改文件夹下所有的文件 |
cls | 清空cmd端口的内容 |
javac -encoding UTF-8
注意:
若是java使用了包文件,在DOS命令中要到项目根目录下使用java 包文件点程序的名称。才能在DOS下找到正确路径
如项目src/com/dream/Test.java文件,编译后在根目录下
需要使用java com.dream.Test进行编译
二、语言基础
1 标识符的使用:
1.1组成部分:
英文大小写字母,数字,$符号,_符号,中文
1.2命名规范:
- 不能以数字开头
- 区分大小写字母
- 不能使用除了$和_以外的特殊符号
- 不要使用中文(企业级的命名规范不允许使用中文)
- 不能使用java的关键词
2 变量:
- 含义:在程序执行的过程中可以改变的量
- 注意:
- 局部变量在使用前必须先初始化
- 同一个区域范围内不能使用两个系统的变量名
- 变量类似于容器,但是变量只能存储单个值
3 类型:
3.1分类:
- 基本数据类型
- 整数型:
- 字节型byte:取值范围[-128,127],1个字节
- 短整型short:取值范围[215,215-1],2个字节
- 整型int:取值范围[231,231-1]即21亿4千7百4十8万多,占4个字节
- 长整型long:取值范围[263,263-1],8个字节
- 浮点型:
- 单精度浮点型float:2个字节
- 双精度浮点型double:4个字节
- 字符型char:取值范围[0,65535],有ASCII可转换。占2个字节
- 布尔型boolean:占4个字节,只有true和false两种结果
- 整数型:
自动转型,由小转大
强转转型,由大转小 数据类型 变量 = (要强转的目标类型)变量;
隐式转换:byte,short,char三者之间不会相互转会,自动转型为int类型
- 引用数据类型
- 数组
- 类
- 接口
- 枚举
- 由于在面向对象中万物皆对象,所以将基本数据类型封装成
- Byte Short Integer Long
- Character
- Float Double
- Boolean
4 运算符
++自增,变量名在前为先使用后自增,反之,先自增再使用,–自减,与自增方法一致,%商
5赋值运算符
等,加等,减等,乘等,除等,余等,的使用
6关系运算符
==, !=, >, >=, <, <=的使用 来做判断是为true否为false
7 逻辑运算符
7.1 &与,&&短路与
两者都是boolean值,同时成立即为true
区别:在判断中,前者需要进行第一个条件不满足后,进行判断第二个条件。后者,只要第一个不满足条件的时候,就不再去判断第二个条件,直接跳出结果。后者效率更高
7.2 |或,||短路或
两者都是boolean值,只要有一个条件满足就为true
区别:同理,前者满足了第一个条件后还会去判断第二个条件。后者只要第一个条件满足了,不在进行判断第二个条件
7.3 ^异或
两个条件相同时为false,不同时为true
7.4 !-置反
将条件反过来
8 字符串拼接符
两侧都是数值时,➕号为算术运算符
有一侧或者两侧都是字符串时,➕号为字符串拼接符
9 三目运算符
数据类型 变量 = (表达式)?值1:值2;
表达式为true,返回值1
表达式为false,返回值2
9.1三目运算符返回值规则
- 值1和值2是常量的情况下,就会按照取值范围大的类型返回数据
- 值1和值2是变量的情况,就会按照取值范围大的类型返回数据
- 值1是常量,值2是变量的情况,值1是否在值2所属类型的取值范围里:
- 在,就按照值2类型返回数据
- 不在,就按照值1类型返回数据
10 位运算符
10.1含义:将十进制的数据转换为二进制再进行运算
10.2 &与:二进制同位比较,两者相同为1,才为1
10.3 |或:二进制同位比较,两者有1,就为1
10.4 ^异或:二进制同位比较,两者相同即为0,不同才为1
10.5 << 左移:整体向左移n位,就用n个0来补位
10.6 >> 右移:整体向右移n位,就用n个最高位补位
10.7 >>无符号位右移:整体向右移动n位,就用0来补位
注意:>>和>>>如果操作数是正数,效果是一样的
正数时,最高位补位为0;
负数时,最高位补位位1;
11 表达式
5 + 6:算数表达式
5 > 6:关系表达式
true & false:逻辑表达式
5 | 6:位运算表达式
12 转义字符
含义:具有特殊意义的字符本身
\n:表示换行
\":表示一个双引号
\':表示一个单引号
\\:表示一个斜杠
\t:表示水平制表
13 常量
13.1 含义:
在程序执行过程中不可变的量
13.2 分类:
- 数字字面量(如:5,18,100,200)
- 字面值常量(如:“榮”,“沝”)
- final修饰的变量(如:final int i=100;)
注意:被final修饰的变量和字面值常量:是存储在常量池中的,常量池出现与JDK1.8版本,是与JDK1.7版本内存中的区别。常量池中的值,直到项目结束才会被销毁
三、条件语句和循环语句
1. if分支语句
1.1 作用场景于判断使用
if(判断表达式){代码块}else{代码块}
if(判断表达式){代码块}else if(判断表达式){代码块}else …(){代码块} else{代码块}
if的表达式:boolean
if:判断单个值、区间、复杂的条件
2.switch分支语句
2.1 作用场景在已知条件中使用
while(表达式){
switch的表达式:byte、short、int、枚举(JDK1.5)、String(JDK1.7) switch:判断单个值
case 1:
代码块
break;
case 2:
代码块
break;
case …:
代码块
break;
default:
代码块;
break;}
3 for循环
3.1使用场景
执行流程:
1.外层for循环进行初始化变量;
2.外层for循环进行判断条件结果必须是boolean类型
2.1 true -执行外层for循环代码块后,进入内层for循环
2.1.1 同理:执行内层for循环初始化变量
2.1.2 执行内层for循环判断条件结果必须是boolean类型
a. true - 执行内层for循环代码块
b. false - 跳出内层循环语句,进入外层循环语句
2.1.3 更新变量
2.2 false - 跳出整个for循环语句
3.更新变量;
4.执行外部的代码块
3.2使用顺序
for(表达式1;表达式2;表达式3){代码块}
1.表达式1—》初始化变量
2.表达式2—》判断
3.代码块
4.表达式3—》更新变量
4 while循环
int i=0;
while(i<3){
System.out.print(6);
i++;
}
5 do…while…循环
int i=0;
do{
System.out.print(6);
i++;
}while(i<3)
6 for VS while VS do…while
6.1. 语法区别:
for(初始化变量;判断条件;更新变量){}
while(判断条件){}
do{}while(判断条件);
循环共同点:判断条件的结果都是boolean值,true-循环 false-跳出循环
6.2. 执行顺序的区别:
for:先判断,再执行
while:先判断,再执行
do-while:先执行一遍,再判断
6.3. 应用场景的区别:
循环次数确定:for
循环次数不确定,先判断,再执行:while
循环次数不确定,先执行一遍,再判断:do-while
7特殊语句
7.1 brek
结束语句
7.2 continue
跳过该循环
7.3 return
返回语句
7.4 lable
作用于多用于for循环后的if嵌套中,给予命名循环
如:http:就是一个命名
四、方法与数组
1.方法:
静态方法、成员方法、构造方法
public class Test{
private String name;
//无参构造
public Test() {
}
//有参构造
public Test(String name) {
this.name = name;
}
//静态方法--无参无返回值
public static void method(){
System.out.println(666);
}
//静态方法--有参有返回值
public static int method01(int a){
a=666;
return a;
}
//静态方法--有参有返回值重载,程序根据程序员的需求自动分配
public static int method01(int a,int b){
a=600;
b=66;
return a+b;
}
//成员方法
public int method(int a){
a=77;
return a;
}
}
class a extends Test{
//子类中重写父类的成员方法
@Override
public int method(int a){
a=666;
return a;
}
}
注意:根据外界需求来使用具体使用方法。但是一定要注意方法不能在调用方法本身,一般情况下方法不调用方法。如果调用方法本身,会造成栈内存溢出错误。
区别点 | 重载方法 | 重写方法 |
---|---|---|
参数列表 | 必须修改 | 一定不能修改 |
返回类型 | 可以修改 | 一定不能修改 |
异常 | 可以修改 | 可以减少或删除,一定不能抛出新的或者更广的异常 |
访问 | 可以修改 | 一定不能做出更严格的限制(可以降低限制) |
斐波那契数列
import java.util.Scanner;
public class Test {
/**
* 不死神兔,兔子都不死,第8个月的兔子数量
* 第N个月共会有多少对兔子
*/
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.print("请输入你想查询的第几个月后有多少对兔子:");
int n=scan.nextInt();
int rabbit = Rabbit(n);
System.out.println("第"+n+"个月后有"+rabbit+"对兔子");
}
private static int Rabbit(int month){
if (month==1||month==2){
return 1;
}
else {
return (Rabbit(month-1))+Rabbit(month-2);
}
}
}
2 数组
2.1一维数组
静态数组 VS 动态数组
//静态数组的3种写法:
int [] num={1,2,3,4,5};
int [] num1=new int[]{1,2,3,4,5};
int [] num2;
num2=new int[]{1,2,3,4,5};
//动态数组
String[] names = new String[5];//5->5个长度
//设置指定下标上的元素
names[0] = "榮a";
names[1] = "榮b";
//都可以使用for循环跟foreach循环进行遍历
2.2二维数组
//冒泡排序
int[] is ={39,77,27,20,45,62};
for(int i=0;i<is.length-1;i++){
for(int j=0;j<is.length-1-i;j++){
if(is[j]>is[j+1]){
int temp=is[j];
is[j]=is[j+1];
is[j+1]=temp;
}
}
}
for(int num:is){
System.out.println(num);
}
//二分法查找
int[] is ={39,77,27,20,45,62};
int num =77;
//排序
Arrays.sort(is);
int start=0;
int end=is.length-1;
while(start<=end){
int mid=(start+end)/2;
if(num)>is[mid]{
start=mid+1;
}else if(num<is[mid]){
end=mid-1;
}else{
System.out.println("查询到了"+num);
break
}
概念:一个开辟了连续的空间的线性数据结构
特点:查询快,增删慢
可以添加任意的数据类型
数组的基本操作
增 删 改 查 长度 判断 排序
冒泡排序 插入排序,选择排序,快速排序
五、面向对象
面向对象编程 OOP AOP(面向切面编程)
类:类是一类事务的模板,把很多具有相同功能的对象抽象出来,描述为一个类
对象:每一个类的具体的实例
类是对象的抽象化,对象是类的实例化
类的主要组成
成员属性,成员方法,构造方法
成员属性:修饰符 数据类型 变量名;
默认值
- 整型:0
- 浮点型:0.0
- 布尔型:false
- 引用类型:null
变量的作用域
局部变量:声明在方法中的变量,作用范围,只在本方法中
成员变量
类变量(static),对象变量
内存位置
堆: 对象变量
方法区:类变量
加载时机
创建对象的时候,对象变量初始化
类被加载的时候,类变量就初始化
份数
对象变量,每一个对象各有一个
类变量,被每一个对象所共享
成员方法
修饰符 返回值 方法名(){
}
方法重载:overload
1:同一个类
2:方法名相同
3:参数列表不同
3.1 参数个数
3.2 参数类型
3.3 参数顺序
和返回值无关
构造器
修饰符 类名(){
}
每一个类至少会有一个构造器,如果没有手动提供构造器,那么编译器会自动提供一个无参的构造器
构造器没有返回值
构造器也可以重载public Student(){
this(“张三”);
}
public Student(String name){
this(“李四”,20);
}
public Student(String name,int age){}
this:代表当前对象的引用
1:this可以调用成员属性
2:this可以调用成员方法
3:this可以调用构造方法
static的用法
修饰变量:代表类变量,被所有的对象共享
修饰方法:代表类方法
修饰类 :静态内部类 细节
成员方法中,既可以直接访问成员变量,也可以访问类变量
静态方法中,只可以访问类变量
成员方法既可以直接调用成员变量,也可以调用类方法
静态方法只可以调用类方法
面向的3个特点
封装,继承,多态
封装:
属性私有化,提供公开的get和set方法 隐藏细节,公开接口
属性的值是随着行为的变化而变化的
修饰符
访问修饰符
private:类可见性
default:类可见,包可见性
protected:类可见,包可见,不同包的子父类
public:项目可见
非访问修饰符
static,final, synchronized,native,transient
继承:单继承,继承链 extends
顶级父类:Object
子类可以继承父类的属性和方法,私有的不能继承
修饰符 class 子类 extends 父类{
}
优点:提高了代码的复用性
缺点:高耦合,低内聚
多态 :
父类 变量名 = new 子类() 向上转型(父类的引用指向子类对象)
多态的必要原则
1:继承
2:要有方法重写
3:向上转型
方法重写 override
1:子父类之间
2:方法名,参数列表,返回值相同
super:代表父类的引用
super.成员属性
super.成员方法
super(参数); 调用父类的构造函数
java中任何一个子类的构造方法都必须调用其父类的构造方法(包括隐示调用)
并且调用父类构造方法的语句必须是子类构造方法的第一条语句
抽象类:就是为了被子类继承
修饰符 abstract class 类名{
}
特点
1:可以有抽象方法
2:可以有实现方法
3:不可以创建对象
4:利用多态通过向上转型,创建子类对象
接口 interface
修饰符 class 类名 implements 接口名{
}
类与类
继承关系,单继承,有继承链
类与接口
实现关系,多实现
接口和接口
继承关系,多继承
抽象类与接口的区别?
变量
抽象类有,接口没有
常量
抽象类有,接口有
public static final 成员方法
抽象类有,接口没有(jdk1.8之前没有)
抽象方法
抽象类有,接口有 public abstract
构造器
抽象类有,接口没有
final的用法
final修饰变量,表示常量,一旦被赋值,不可被修改 final修饰方法,表示这个方法不能被重写
final修饰类,表示是一个最终类,不能被继承(所有的方法不能被重写)
六、枚举:enum
枚举里的变量默认的修饰符是public static final
public enum Season(){
春,夏,秋,冬
}
Season.春
Season[] son = Season.values();
for(Season s:son){
System.out.println(s.name)
}
七、集合
Collection
List
ArrayList:底层是数组,查询快,增删慢,不同步
LinkedList:底层是链表,查询慢,增删快,不同步
Vector:底层是数组,查询快,增删慢,同步
List接口:
有序(添加顺序和迭代顺序一致)且重复
List接口的遍历方式
1:转数组 toArray
ArrayList al = new ArrayList<>();
2:size+get List的专有遍历方式
for(int i = 0;i<al.size();i++){
al.get(i);
}
3:迭代器 Iterator it = al.iterator(); Collection的专有遍历方式
while(it.hasNext()){
it.next()
}
4:for-each-- 任何集合都可以
for(String s:al){
s
}
Set
HashSet:底层是哈希表(数组+链表)查询快,增删快,不同步
LinkedHashSet:底层是哈希表+链表 查询快,增删快,不同步
TreeSet:底层是树结构,排序
2种排序方案
1:自然排序,实现Comparable接口,重写comparTo()
2:比较器排序,实现Comparator接口,重写compare()
Set接口:
无序且唯一
Map
HashMap:
底层是哈希表(数组+链表)查询快,增删快,不同步
TreeMap:
底层是树结构,排序
2种排序方案
1:自然排序,实现Comparable接口,重写comparTo()
2:比较器排序,实现Comparator接口,重写compare()
Hashtable:
底层是哈希表(数组+链表)查询快,增删快,同步
Map集合遍历方式
1:先找到所有的键吗,然后根据键获取值
Map<String,String> map = new HashMap<>();
Set set = map.keySet();
for(String s:set){
String value = map.get(s);
}
2:直接获取键值对 entrySet
Set<EntrtSet<String,String>> set = map.entrySet();
for(EntrtSet<String,String> en :set){
en.getKey(); 键
en.getValue(); 值
}
集合的工具类:Collections
添加 add()
删除 remove()
修改
排序 sort()
二分搜索法:binarySearch() 前提是先排序
八、常用类
包装类
Byte,Short,Integer,Long,Float,Double,Boolean,Character
字符串 :String:是一个不可变的字符序列
“abcde”.substring(0,2) = “ab”
“abc”.charAt(0) = ‘a’
“abc”.length() = 3
“a,b,c”.split(",") = [“a”,“b”,“c”]
“abc”.indexof(“a”) = 0
“abaca”.replaceAll(“a”,"") = “bc”;
字符串缓冲类
StringBuffer:可变的字符序列 同步
StringBuilder: 可变的字符序列 不同步
正则表达式
具有正确规则的字符串的表达式
[0-9a-z_A-Z]
{a}? 0-1
{a}* 0-N
{a}+ 1-N
{3,6} 3-6
判断
boolean flag = “abc”.matcher(regex)
分割
String[] str = “a,b,c”.split(regex);
替换
“abc”.replaceAll(“a”,regex);
获取
String regex = “\b[a-z]{3}\b”;
Pattern pt = new Pattern();
Matcher mt = pt.complie(regex);
while(matcher.find()){
mt.group();
}
数学类:Math
random() 0-1 之间的小数 包括0,不包括1
max(int a,int b);
min(int a,int b);
ceil(10.123) = 11
floor(10.123) = 10
pow(10,3) = 1000 次幂函数
日期类:java.util.Date
Date date = new Date(); 获取当前系统时间
getYear()+1900
getMonth()+1
getDate()
getDay()
getHours();
getMinutes()
getSeconds()
日期转为字符串
date.toLocalString();
日期转换类 DateFormat 子类 SimpleDateFormat
DateFormat df = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
Date date = new Date();
//将日期转为字符串
String s = date.format(date);
//将字符串转为日期
Date da = date.parse(“1999-12-12”);
日历类 Calendar
Calendar ca = Calendar.genInstance();
ca.get(Calendar.YEAR); 获取年
ca.get(Calendar.MONTH); 获取月
ca.get(Calendar.DATE); 获取日
大整型 BigInteger
BigInteger bg = new BigInteger(String.valueof(Long.MAX_VALUE))
bg = bg.add(new BigInteger(“1”)); 加法 给long的最大值+1
大浮点型 BigDecimal
BigDecimal bd = new BigDecimal(String.valueof(Double.MAX_VALUE))
bd = bg.add(new BigDecimal(“1”)); 加法 给double的最大值+1
九、异常
分类:Throwable、Exception 异常
Throwable
子类
Exception 异常
编译时异常
运行时异常 RuntimeException
Error 错误
处理异常
1:捕获异常
try:尝试运行有可能会出错的代码
catch:一旦代码出错,编译器生成一个异常对象,和catch中异常做匹配,匹配成功进入catch块,后面的代码正常执行
finally:表示一定会执行,就算代码中有return,也会在return之前执行,除了虚拟机强制退出 System.exit(1);
2:抛出异常
throws:在方法声明部分,抛出一个异常类,可以一次性声明多个异常
有可能会抛出异常
throw
在方法体中,抛出一个异常对象,一定会抛出异常
3:自定义异常
1:继承Exception或者RuntimeException
2:提供一个无参的,以及有参的构造函数
十、多线程
实现方式
1:继承Thread类,重写run方法
2:实现Runnable接口, 重写run方法
启动方式1 继承方案
public class MyThread extends Thread{
@OverRide
public void run(){
多线程
}
main(){
MyThread m1 = new MyThread();
MyThread m2 = new MyThread();
m1.setName("线程1");
m2.setName("线程2");
m1.start();
m2.start();
}
}
启动方式2 接口方式
public class MyThread implements Runnable{
@OverRide
public void run(){
多线程
}
main(){
MyThread m1 = new MyThread();
Thread t1 =new Thread(m1,"线程1");
Thread t2 =new Thread(m1,"线程2");
t1.start();
t2.start();
}
}
线程声明周期
新生:new对象
就绪:调用start方法
运行:谁抢到CPU执行,就运行
阻塞:调用sleep()或者wait()休眠时间结束,进入就绪被唤醒进入就绪 (notify,notifyAll)
死亡 stop,interrupted
线程同步
1:同步代码块
synchronized(锁对象){
需要同步的代码…
}
2:同步方法
public synchronized void show(){
需要同步的代码…
}
3:Lock锁
lock.lock();
需要同步的代码…
lock.unLock();
死锁
public class DieLock implements Runnable{
public static final Object objA = new Object();
public static final Object objB = new Object();
public boolean flag;
public DieLock(boolean flag){
this.flag = flag;
}
@OverRide
public void run(){
if(flag){
synchronized(objA){
synchronized(objB){}
}
}else{
synchronized(objB){
synchronized(objA){}
}
}
}
main(){
DieLock d1 = new DieLock(true);
DieLock d2 = new DieLock(false);
Thread t1 = new Thread(d1);
Thread t2 = new Thread(d2);
t1.start();
t2.start();
}
}
十一、文件类:File
File file = new File(“d://工具//a.txt”);
file.createNewFile();
renameTo()
delete();
十二、IO流
字节流
OutputStream
FileOutputStream 文件字节输出流
BufferedOutputStream 缓冲字节输出流
ObjectOutputStream 序列化流 将对象流化(将java对象保存在文件)
InputStream
FileInputStream 文件字节输入流
BufferedInputStream 缓冲字节输入流
ObjectInputStream 反序列化流:将文件中对象读取取java程序中
字符流
Writer
OutputStreamWriter 字符输出转换流
FileWriter 字符输出便捷流
BufferedWriter 字符输出缓冲流
Reader
InputStreamReader 字符输入转换流
FileReader 字符输入便捷流
BufferedReader 字符输入缓冲流
3层结构的流
1:缓冲流
2:转换流
3:字节流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(“a.txt”)))
BufferedReader bw = new BufferedReader(new InputStreamReader(new FileInputStream(“a.txt”)))
流拷贝文件
把d://工具/中国人.mp3 拷贝到当前项目
BufferedInputStream bis = new BufferedInputStream(“d://工具/中国人.mp3”);
BufferedOutputStream bos = new BufferedOutputStream(“中国人.mp3”);
byte[] by = new byte[1024];
int num = 0;
while((num = bis.read(by))!=-1){
bos.write(by,0,num);
}
bos.close();
bis.close();
把d://工具/a.txt 拷贝到当前项目
BufferedReader br = new BufferedReader(“d://工具/a.txt”);
BufferedWriter bw = new BufferedWriter(“a.txt”);
String line = null;
while((line = br.readLine())!=null){
bw.write(line);
bw.newLine();
}
bw.close();
br.close();
序列化:
需要实现序列化的类要实现Serializable 接口
方案1:
Student stu1 = new Student(); Student stu2 = new Student();
ObjectOutputStream oos = new ObjectOutputStream(“Student.txt”);
oos.writerObject(stu1);
oos.writerObject(stu2);
oos.writerObject(null); //自定义结束标记 oos.close();
ObjectInputStream ois = new ObjectInputStream(“Student.txt”); Object obj = null; while((obj = ois.readObject())!=null){
Student stu = (Student)obj }ois.close();
方案2:
Student stu1 = new Student(); Student stu2 = new Student();
ArrayList al = new ArrayList<>(); al.add(stu1); al.add(stu2);
ObjectOutputStream oos = new ObjectOutputStream(“Student.txt”);
oos.writerObject(al); oos.close();
ObjectInputStream ois = new ObjectInputStream(“Student.txt”);
ArrayLis al = (ArrayLis)ois.readObject();
for(Student stu:al){
stu
} ois.close();
十三、网络编程:Socket编程
网络编程3要素
1:IP地址 5类 2:端口号 0-65535 3:协议
TCP
面向连接 3次握手协议
安全,效率低
可传输大量数据
tcp客户端
1:创建客户端的套接字
Socket s = new Socket(InetAddress.getLocalHost(),10086);
2:获取输出流
BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
3:获取输入流
BufferedIntputStream bis = new BufferedIntputStream(s.getIntputStream());
3:写数据
bos.writer(“你好吗”.getBytes());
4:通知服务器,写入数据完毕
s.shutdownOutput();
5:读取服务器给出的响应
bis.read();
6:关闭套接字
s.close();
tcp服务器端
1:创建服务器端的套接字
ServerSocket ss = new ServerSocket(10086);
2:监听客户端套接字,并获取套接字
Socket s = ss.accept();
3:获取输入流
BufferedIntputStream bis = new BufferedIntputStream(s.getIntputStream());
4 获取输出流
BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
5:读数据
byte[] by = new byte[1024];
int num = 0;
while((num = bis.read(by))!=-1){
new String(by,0,num);
}
6:给出响应信息
bos.write(“反馈信息”.geBytes());
bos.flush();
5:关闭套接字
s.close();
UDP
非面向连接
不安全,下率高
传输数据量小
可以广播发送
udp发送端
1:创建发送端的socket
DatagramScoket ds = new DatagramScoket();
2:创建数据包
byte[] by = {97,98,99};
DatagramPacket dp = new DatagramPacket(by,by.length,InetAddress.getLocalHost(),10086);
3:发送数据包
ds.send(dp);
4:关闭socket
ds.close();
udp接受端
1:创建接受端的socket
DatagramScoket ds = new DatagramScoket(10086);
2:创建数据包
byte[] by = new byte[1024];
DatagramPacket dp = new DatagramPacket(by,by.length);
3:接受数据包
ds.receive(dp);
4:拆包
byte[] by2 = dp.getDatea(); 数据
int len = dp.getLneght(); 数据长度
InetAddress address = dp.getAddress(); 发送端的ip
new String(by2,0,len);
5:关闭socket
ds.close();
十四、注解和反射
注解
1.含义
java.annotation包
Annotaion是从JDK1.5开始引入的新技术,注解既可以对程序解释又可以对程序员解释
2.注解与注释的区别
注解:对程序员进行代码信息解释
注释:对程序和程序员进行代码信息解释
3.注解的使用
- 不是程序本身,可以对程序作出解释(与注释(comment)类似)
- 可以呗其他程序(编译器)读取
4.注解的格式
注解是以"@注释名"在代码中存在的,还可以添加一些参数
如:@SuppressWarnings(value=“all”) 当然只有一个值的时候可以不写,会默认为value的值,但是多个值的时候必须写
5.注解的应用
可以附加到package、class、method、field等上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制实现这些数据的访问
6.内置注解
@Override:定义在java.lang.Override中,次注解只适用于修饰方法,表示一个方法声明打算重写超累中的类一个方法声明
@Deprecated:定义在java.lang.Deprecated中.次注解可以使用在修饰方法,属性,类。表示不鼓励使用这样的元素。通常是因为它很危险或存在更好的选择
@SuppressWarnings:
- 镇压警告,定义在java.lang.SuppressWarnings中用来抑制编译时的警告信息,与前两个注释有所不同。
- 需要添加参数才能正确使用。
- 这些参数都是已经定义好了的直接选择性使用就可以了:
- @SuppressWarnings(“all”)抑制所有类型的警告信息
- @SuppressWarnings(“unchecked”)抑制单类型的警告信息
- @SuppressWarnings(value={“unchecked”,"deprecation})抑制多类型的警告信息
7.元注解
元注解的作用:负责注解其他注解,Java定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型的作用说明
这些类型和它们所支持的类在java.lang.annotation包中可以找到
(@Target,@Retention,@Document,@Inherited)
@Target: 用于描述注解的使用范围(即:被描述的注解,可以用在什么地方)
@Retention:表示需要在上面级别保存该注解信息,用于描述注解的生命周期
(SOURCE < CLASS < RUNTIME)
@Document:说明该注解将被包含在javadoc中
@Inherited:说明子类可以继承父类中的该注解
8.自定义注解
使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口
分析:
- @interface 用来声明一个注解,格式:public @interface 注解名(定义内容)
- 其中每个方法实际上就是声明了一个配置参数
- 方法的名称就是参数的名称
- 返回值类型就是参数的类型(返回值只能是基本类型、Class、String、enum)
- 可以通过default来声明参数的默认值
- 如果只有一个参数成员,一般参数名为value()
- 注解元素必须要有值,我们定义注解元素时,经常使用空字符串和0作为默认值
public class Test{ //注解显示分支,参数没有默认值就必须赋值 //@MyAnnotation(name="xxx",strs={"001","002"}) @MyAnnotation("XXX")//默认赋值给注解里value的参数 public static void main(String[] args){ } @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotaion{ String value(); } }
反射
1:获取Class
Class clazz = Class.foName(“java.lang.String”);
2:获取构造器 public
Constructor con = clazz.getConstructor(String.class);
获取构造器 所有
Constructor con2 = clazz.getDeclaredConstructor(String.class);
3:创建对象
Object obj = clazz.newInstance(); 无参对象
Object obj = con.newInstance(“字符串”);
4:获取属性
Field field = clazz.getField(“name”,String.class);
5 暴力破解
field.setAccessable(true);
6:属性赋值
field.set(obj,“张三”);
7:获取属性值
field.get(obj);
8:获取方法
Method m = clazz.getMethod(“add”,String.class);
9调用方法
Object obj = m.invoke(obj,“你好”);