配置环境,把JDK的bin所在路径复制到Path,末尾加;
基本语法
一 常见的DOS命令
盘符的切换 d:回车
目录的进入 cd javase
cd javaseday01code
目录的回退 cd..
cd
清屏 cls
退出 exit
二 标识符
(1)就是给类,接口,方法,变量等起名字的字符序列
(2)组成规则:A:英文大小写字母 B:数字 C:$和_
(3)注意事项:A:不能以数字开头 B:不能是java中的关键字 C:区分大小写
(4)常见的命名规则(见名知意)
A:包 全部小写
单级包:小写
多级包:小写,并用.隔开
B:类或者接口
一个单词:首字母大写
多个单词:每个单词首字母大写
C:方法或者变量
一个单词:首字母小写
多个单词:从第二个单词开始,每个单词首字母大写
D:常量
全部大写
一个单词:大写
多个单词:大写,并用_隔开
三 关键字
被Java语言赋予特定含义的单词。全部小写。
四 注释
(1) 单行注释 //
(2) 多行注释 /* */
(3) 文档注释 /** */
五 进制转换(了解)
(1)其他进制到十进制
系数:就是每一个位上的数值
基数:x进制的基数就是x
权:对每一个位上的数据,从右,并且从0开始编号,对应的编号就是该数据的权。
结果:系数*基数^权次幂之和。
(2)十进制到其他进制
除基取余,直到商为0,余数反转。
(3)进制转换的快速转换法
A:十进制和二进制间的转换:8421码。
B:二进制到八进制,十六进制的转换
六 数据类型
(1)分类:
A:基本数据类型:4类8种
B:引用数据类型:类,接口,数组。
(2)基本数据类型
A:整数 占用字节数
byte 1
short 2
int 4
long 8
B:浮点数
float 4
double 8
C:字符
char 2
D:布尔
boolean 1
注意:整数默认是int类型,浮点数默认是double。
长整数要加L或者l。
单精度的浮点数要加F或者f。
(3)变量的定义格式:
A: 数据类型 变量名 = 初始化值;
B: 数据类型 变量名;
变量名 = 初始化值;
(4)数据类型转换
①boolean类型不参与转换
②默认转换
A:从小到大——源类型<目标类型
B:byte,short,char -- int -- long -- float -- double
③强制转换
A:从大到小
B:格式:目标数据类型 变量名 = (目标数据类型) (被转换的数据);
七 运算符
(1) A:赋值运算符 =
B:扩展的赋值运算符 += , -= , *= , /= ,%= . 其特点:隐含了自动强制转换。如:
面试题:short s = 1;
s = s + 1;
short s = 1;
s += 1;
请问上面的代码哪个有问题?答:上面的错,下面的对,因为+=默认强制转换。
(2) 算术运算符
A: + , - , * , / , % , ++ , --
B: +的用法: a:加法 b:正号 c:字符串连接符
C: /和%的区别: /取得是商,%取得是余数
D:++和--的用法: a:自增或者自减
b:使用:
单独使用:放在操作数据的前面和后面效果一样,如a++或者++a效果一样。
参与操作使用:放在操作数的前面:先自增或者自减,再参与操作放在操作数的后面:先参与操作,再自增或者自减(就算再输出语句里也是先输出,再运算)
(3) 关系运算符 == != > >= < <= (千万不要把==写成了=)
(4) 逻辑运算符:
&& 并且 (两个表达式同时为真,结果才为真)
|| 或 (两个表达式只要有一个为真,,结果就为真)
! 非
^ 相同则false,不同则true。情侣关系。
三元运算符:比较表达式?表达式1:表达式2;
执行流程:
首先计算比较表达式的值,看是true还是false。
如果是true,表达式1就是结果。
如果是false,表达式2就是结果。
用途a: 比较两个数据是否相等b:获取两个数据中的最大值c:获取三个数据中的最大值
(5) 优先级别:算术、比较、逻辑
八 键盘录入
(1)导包,import java.util.Scanner;
(2)创建对象,Scanner sc = new Scanner(System.in);
(3)获取数据,int x = sc.nextInt();
九 流程控制语句
A :if选择结构语法
(1)if(条件){}
(2)if(条件){}else{}
(3)if(条件){}else if(条件){}else if(条件) { }else{}
B:while循环
(1)while(判断条件){循环体语句;迭代因子;}
(2)do{循环体语句;迭代因子;}while(判断条件);
(3)for(初始化;判断条件;迭代因子){ 循环体语句;}
C:switch语句
switch(表达式) {
case 值1:
break;}
顺序结构是程序中最简单最基本的流程控制,没有特定的语法结构,按照代码的先后顺序,依次执行,程序中大多数的代码都是这样执行的。
注意点:
1 if语句和switch语句各自的场景
A:if 针对boolean类型的判断
针对一个范围的判断
针对几个常量的判断
B:switch
针对几个常量的判断 (case后面只能是常量,不能是变量)
2 循环使用的注意事项(死循环)
最简单的死循环格式
a: while(true) { ... }
b:for( ; ; ) { }
十 控制跳转语句
(1)break:中断
A:用在循环和switch语句中,离开此应用场景无意义。
B:作用
a:跳出单层循环
b:跳出多层循环,需要标签语句的配合(在循环前面写个名字就定义了个标签)
(2)continue:继续
A:用在循环中,离开此应用场景无意义。
B:作用 a:跳出单层循环的一次,可以继续下一次(但本次的运行结果就不显示了)
(3)return:返回
A:用于结束方法的
B:一旦遇到return,程序就不会在继续往后执行,直接结束了。(System.exit(0); 强制退出系统)
数组
一 数组:存储同一种数据类型的多个元素的容器。
1特点:每一个元素都有索引,从0开始,最大索引是(长度-1)。
2定义格式
A:数据类型[] 数组名; B:数据类型 数组名[];(这个不常用)
3数组的初始化
A:动态初始化:只给长度,系统给出默认值
举例:int[] arr = new int[3];
B:静态初始化:给出值,系统决定长度
举例:int[] arr = new int[]{1,2,3};
简化版:int[] arr = {1,2,3};
4 Java的内存分配
A:栈 存储局部变量
B:堆 存储所有new出来的
C:方法区(面向对象部分详细讲解)
D:本地方法区(系统相关)
E:寄存器(CPU使用)
注意:a:局部变量 在方法定义中或者方法声明上定义的变量。
b:栈内存和堆内存的区别
栈:数据使用完毕,就消失。
堆:每一个new出来的东西都有地址
(每一个变量都有默认值byte,short,int,long 0;float,double 0.0;char 'u0000';boolean false;引用类型 null。数据使用完毕后,在垃圾回收器空闲的时候回收)
5数组内存
将数组a的引用赋值给了数组b(即b=a),这赋的是地址值,就是两个栈变量指向同一个堆内存,所以不论对a,b谁做改动,都会改变那个它们同时指着的数组。
6数组的常见操作
A:遍历
for(int x=0; x<arr.length; x++) { System.out.println(arr[x]); } //foreach方法遍历更好用,还能用于集合的遍历: for(object i:arr) { System.out.print(i); }
B:逆序
方式1:for(int x=0; x<arr.length/2; x++) { int temp = arr[x]; arr[x] = arr[arr.length-1-x]; arr[arr.length-1-x] = temp; } 方式2:for(int start=0,end=arr.length-1; start<=end; start++,end--) { int temp = arr[start]; arr[start] = arr[end]; arr[end] = temp; }
C:查表
public static String getString(String[] strArray,int index) { return strArray[index]; }
D:基本查找
public static int getIndex(int[] arr,int value) { int index = -1; for(int x=0; x<arr.length; x++) { if(arr[x] == value) { index = x; break; } } return index;(某值不存在,规定返回-1) }
二 二维数组
(1)元素是一维数组的数组。
(2)格式:
A:数据类型[][] 数组名 = new 数据类型[m][n];
B:数据类型[][] 数组名 = new 数据类型[m][];
C:数据类型[][] 数组名 = new 数据类型[][]{{...},{...},{...}};
D:数据类型[][] 数组名 = {{...},{...},{...}};
面向对象
一 什么是面向对象
1定义:面向对象是基于面向过程的编程思想
2特点:万事万物皆对象
3类与对象
类:是一组相关的属性和行为的集合。是一个抽象的概念。
对象:是该类事物的具体存在,是一个具体的实例。
4 Java程序的开发,设计和特征
A:开发:就是不断的创建对象,通过对象调用功能
B:设计:就是管理和维护对象间的关系
C:特征a:封装b:继承c:多态
5 类的构成:变量 、方法。
6 类的使用: a:先创建对象: 类名 对象名 = new 类名();
b:再使用成员变量和成员方法: 对象名.成员变量 对象名.成员方法()
7 方法
(1)方法:就是完成特定功能的代码块。
注意:在很多语言里面有函数的定义,而在Java中,函数被称为方法。
(2)格式:
修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 参数名2...) {
方法体语句;
return 返回值;
}
修饰符:比如 public static
返回值类型:就是功能结果的数据类型
方法名:就是起了一个名字,方便我们调用该方法。
参数类型:就是参数的数据类型
参数名:就是变量
参数分类: 实参:实际参与运算的数据
形参:方法上定义的,用于接收实际参数的变量
方法体语句:就是完成功能的代码块
return:结束方法
返回值:就是功能的结果,由return带给调用者。
(3)两个明确:
返回值类型:结果的数据类型
参数列表:参数的个数及对应的数据类型
(4)方法调用
A:有明确返回值的方法
a:单独调用,没有意义
b:输出调用,不是很好,因为我可能需要不结果进行进一步的操作。
c:赋值调用,推荐方案
B:无返回值类型的调用
a:单独调用可以,输出调用错误,赋值调用也错误。
(5)方法的注意事项
A:方法不调用不执行
B:方法之间是平级关系,不能嵌套定义
C:方法定义的时候,参数是用,隔开的
D:方法在调用的时候,不用在传递数据类型:如sum(int x, int y)里的int就没必要写。另外像sum(20,30)这样,里面是常量的也可以。
E:如果方法有明确的返回值类型,就必须有return语句返回。
F:同一类中有多个方法,在一个方法里调别的方法,直接用方法名,不用再建
对象。
(7)方法重载
同一个类中,针对方法的功能相同,参数列表不同的情况,为了见名知意,java允许它们起一样的名字。
jvm会根据不同的参数调用不同的功能,与返回值类型无关,只看方法名和参 数列表。这就叫方法重载。
参数列表不同:参数的个数不同。
参数的对应的数据类型不同。
(8)重载与重写
A:方法重写:子类中出现了和父类中方法声明一模一样的方法。
方法重载:本类中出现的方法名一样,参数列表不同的方法。与返回值无关。
B:子类对象调用方法的时候:先找子类本身,再找父类。
C:方法重写的应用:
当子类需要父类的功能,而功能主体子类有自己特有内容,就重写父类中的方法。这样,即沿袭了父类的功能,又定义了子类特有的内容。
D:方法重写的注意事项:
a:父类中私有方法不能被重写因为父类私有方法子类根本就无法继承。
b:子类重写父类方法时,访问权限不能更低。最好就一致。
c:父类静态方法,子类也必须通过静态方法进行重写。其实这个算不上方法重写,但是现象确实如此。
d:子类重写父类方法的时候,最好声明一模一样。
二 具体内容
1:成员变量和局部变量的区别
(1)在类中的位置不同
成员变量:类中方法外
局部变量:方法定义中或者方法声明上
(2)在内存中的位置不同
成员变量:在堆中
局部变量:在栈中
(3)生命周期不同
成员变量:随着对象的创建而存在,随着对象的消失而消失
局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
(4)初始化值不同
成员变量:有默认值
局部变量:没有默认值,必须定义,赋值,然后才能使用
2:类作为形式参数
如果你看到一个方法需要的参数是一个类名,就应该知道这里实际需要的是一个具体的对象。
3:匿名对象
(1)没有名字的对象
(2)应用场景
A:调用方法,仅仅只调用一次的时候。
b:可以作为实际参数传递。
4:封装
(1)隐藏实现细节,提供公共的访问方式
(2)好处:
A:隐藏实现细节,提供公共的访问方式
B:提高代码的复用性
C:提高代码的安全性
(3)设计原则
把不想让外界知道的实现细节给隐藏起来,提供公共的访问方式
(4)private是封装的一种体现。
封装:类,方法,private修饰成员变量
5:private关键字
(1)私有的意义,可以修饰成员变量和成员方法
(2)特点:
被private修饰的后的成员只能在本类中被访问
(3)private的应用:
以后再写一个类的时候:
把所有的成员变量给private了
提供对应的getXxx()/setXxx()方法
6:this关键字
(1)代表当前类的引用对象
哪个对象调用方法,该方法内部的this就代表那个对象
(2)this的应用场景:
A:解决了局部变量隐藏成员变量的问题(和setXxx()配合使用)
B:引用本类方法外的变量。
7:构造方法
(1)作用:用于对对象的数据进行初始化
(2)格式:看下面例子
(3)构造方法的注意事项
A:如果我们没写构造方法,系统将提供一个默认的无参构造方法
B:如果我们给出了构造方法,系统将不再提供默认构造方法
如果这个时候,我们要使用无参构造方法,就必须自己给出。
推荐:永远自己手动给出无参构造方法。
(4)给成员变量赋值的方式
A:setXxx() B:带参构造方法 (看下面测试)
(5)标准案例
class Student { private String name; private int age; public Student(){} public Student(String name,int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; }
}
测试:
class StudentDemo { public static void main(String[] args) { //方式1 (setXxx()方法,常用) Student s1 = new Student(); s1.setName("林青霞"); s1.setAge(27); System.out.println(s1.getName()+"---"+s1.getAge()); //方式2 (带参构造方法,维护性较差) Student s2 = new Student("刘意",30); System.out.println(s2.getName()+"---"+s2.getAge()); } }
8:代码:Student s = new Student();做了哪些事情?
(1)把Student.class文件加载到内存
(2)在栈内存为s开辟空间
(3)在堆内存为学生对象申请空间
(4)给学生的成员变量进行默认初始化。null,0
(5)给学生的成员变量进行显示初始化。林青霞,27
(6)通过构造方法给成员变量进行初始化。刘意,30
(7)对象构造完毕,把地址赋值给s变量
9:static关键字
(1)静态的意思。可以修饰成员变量和成员方法。
(2)静态的特点:
A:随着类的加载而加载
B:优先与对象存在
C:被类的所有对象共享
这其实也是我们判断该不该使用静态的依据。举例:饮水机和水杯的问题思考
D:可以通过类名调用
既可以通过对象名调用,也可以通过类名调用,建议通过类名调用。
(3)静态的内存图:静态的内容在方法区的静态区
(4)静态的注意事项;
A:在静态方法中没有this对象
B:静态只能访问静态(代码测试过)
(5)静态变量和成员变量的区别
A:所属不同
静态变量:属于类,类变量
成员变量:属于对象,对象变量,实例变量
B:内存位置不同
静态变量:方法区的静态区
成员变量:堆内存
C:生命周期不同
静态变量:静态变量是随着类的加载而加载,随着类的消失而消失
成员变量:成员变量是随着对象的创建而存在,随着对象的消失而消失
D:调用不同
静态变量:可以通过对象名调用,也可以通过类名调用
成员变量:只能通过对象名调用
(6)main方法是静态的
public:权限最大
static:不用创建对象调用
void:返回值给jvm没有意义
main:就是一个常见的名称。
String[] args:可以接收数据,提供程序的灵活性(现在都用Scanner了)
10:制作帮助文档
(1)写一个类
(2)加入文档注释
(3)通过javadoc工具生成即可
11:通过JDK提供的API学习了Math类
(1)API(Application Programming Interface)应用程序编程接口(帮助文档)
(2)如何使用呢?请参照 如何使用帮助文档.txt
(3)Math类
A:是针对数学进行操作的类
B:没有构造方法,因为它的成员都是静态的
C:产生随机数
public static double random(): [0.0,1.0)
D:如何产生一个1-100之间的随机数
int number = (int)(Math.random()*100)+1;
E:猜数字小游戏
12:代码块
(1)用{}括起来的代码。
(2)分类:
A:局部代码块:用于限定变量的生命周期,及早释放,提高内存利用率。
B:构造代码块:把多个构造方法中相同的代码可以放到这里,每个构造方法执行前,首先执行构造代码块。
C:静态代码块:对类的数据进行初始化,仅仅只执行一次。
(3)静态代码块,构造代码块,构造方法的顺序问题
静态代码块 > 构造代码块 > 构造方法
13:继承
(1)把多个类中相同的成员给提取出来定义到一个独立的类中。然后让这多个类和该独立的类产生一个关系,这多个类就具备了这些内容。这个关系叫继承。
(2)格式:
class 子类名 extends 父类名 {}
(3)好处:
A:提高了代码的复用性
B:提高了代码的维护性
C:让类与类产生了一个关系,是多态的前提
(4)弊端:
A:让类的耦合性增强。这样某个类的改变,就会影响其他和该类相关的类。
原则:低耦合,高内聚。
耦合:类与类的关系
内聚:自己完成某件事情的能力
B:打破了封装性
(5)特点:
A:Java中类只支持单继承(一个子类只能继承一个父类)
B:Java中可以多层(重)继承(继承体系)
(6)注意事项:
A:子类不能继承父类的私有成员
B:子类不能继承父类的构造方法,但是可以通过super去访问
C:不要为了部分功能而去继承
D:子类中所有的构造方法都会默认访问父类中的无参构造。
(7)什么时候使用继承?
继承体现的是:is a的关系。(右边is a左边,如果读得通,就可以用继承)
(8)Java继承中的成员关系
A:成员变量
a:子类的成员变量名称和父类中的成员变量名称不一样,这个太简单
b:子类的成员变量名称和父类中的成员变量名称一样,这个怎么访问呢?
子类的方法访问变量的查找顺序:
在子类方法的局部范围找,有就使用。
在子类的成员范围找,有就使用。
在父类的成员范围找,有就使用。
找不到,就报错。这叫就近原则。
B:构造方法
a:子类的构造方法默认会去访问父类的无参构造方法是为了子类访问父类数据的初始化
b:父类中如果没有无参构造方法,怎么办?
子类通过super去明确调用带参构造
子类通过this调用本身的其他构造,但是一定会有一个去访问了父类的构造
C:成员方法
a:子类的成员方法和父类中的成员方法名称不一样,这个太简单
b:子类的成员方法和父类中的成员方法名称一样,这个怎么访问呢?
通过子类对象访问一个方法的查找顺序:
在子类中找,有就使用
在父类中找,有就使用
找不到,就报错
14:final关键字
(1)是最终的意思,可以修饰类,方法,变量。
(2)特点:A:它修饰的类,不能被继承。
B:它修饰的方法,不能被重写。
C:它修饰的变量,是一个常量。
(3)面试相关:(详情参见 some_problemsFinalTest1,FinalTest2)
A:局部变量
a:基本类型 值不能发生改变
b:引用类型 地址值不能发生改变,但是对象的内容是可以改变的 写过final Student ss = new Student();再写ss=new Student();就变了地址值,不对
B:初始化时机:推荐定义的时候。
补充:java中类的初始化顺序
执行顺序是:首先是父类静态块-->然后是子类静态块-->父类自由块-->父类构造函数块-->子类自由块-->子类构造函数块
15:多态
(1)同一个对象在不同时刻体现出来的不同状态。
(2)多态的前提:
A:有继承或者实现关系。
B:有方法重写。
C:有父类或者父接口引用指向子类对象。
多态的分类:
a:具体类多态
class Fu {} class Zi extends Fu {} Fu f = new Zi();
b:抽象类多态
abstract class Fu {} class Zi extends Fu {} Fu f = new Zi();
c:接口多态
interface Fu {} class Zi implements Fu {} Fu f = new Zi();
(3)多态中的成员访问特点
A:成员变量:编译看左边,运行看左边
B:构造方法:子类的构造都会默认访问父类构造
C:成员方法:编译看左边,运行看右边
D:静态方法:编译看左边,运行看左边
(4)多态的好处:
A:提高代码的维护性(继承体现)
B:提高代码的扩展性(多态体现)
(5)多态的弊端:
父不能使用子的特有功能。即 子可以当作父使用,父不能当作子使用。
(6)多态中的转型
A:向上转型
从子到父 孔子爹 k爹 = new 孔子();
B:向下转型
从父到子 孔子 k = (孔子) k爹;
16:抽象类
(1)把多个共性的东西提取到一个类中,声明其方法,但不给出具体的方法体,这叫抽象方法。在一个类中如果有抽象方法,该类必须定义为抽象类。
(2)特点
A:抽象类和抽象方法必须用关键字abstract修饰
B:抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类
C:抽象类不能实例化
D:抽象类的子类
a:是一个抽象类。
b:是一个具体类。这个类必须重写抽象类中的所有抽象方法。
(3)成员特点:
A:成员变量:有变量,有常量
B:构造方法:有构造方法
C:成员方法:有抽象,有非抽象
(4)几个小问题
A:抽象类有构造方法,不能实例化,那么构造方法有什么用?
用于子类访问父类数据的初始化
B:一个类如果没有抽象方法,却定义为了抽象类,有什么用?
为了不让创建对象
C:abstract不能和哪些关键字共存
a:final 冲突 b:private 冲突 c:static 无意义
17:接口
(1)额外的功能。
(2)特点:
A:接口用关键字interface修饰
interface 接口名 {}
B:类实现接口用implements修饰
class 类名 implements 接口名 {}
C:接口不能实例化
D:接口的实现类
a:是一个抽象类。
b:是一个具体类,这个类必须重写接口中的所有抽象方法。
(3)成员特点:
A:成员变量:只能是常量,默认修饰符:public static final
B:构造方法:没有构造方法
C:成员方法:只能是抽象的,默认修饰符:public abstract
(4)类与类,类与接口,接口与接口
A:类与类
继承关系,只能单继承,可以多层继承
B:类与接口
实现关系,可以单实现,也可以多实现。(多个接口用逗号隔开)
还可以在继承一个类的同时,实现多个接口
C:接口与接口
继承关系,可以单继承,也可以多继承
(5)抽象类和接口的区别
A:成员区别
抽象类:
成员变量:可以变量,也可以常量
构造方法:有
成员方法:可以抽象,也可以非抽象
接口:
成员变量:只可以常量
成员方法:只可以抽象
B:关系区别(看上面的(4))
C:设计理念不同
抽象类:is a,抽象类中定义的是共性功能。
接口:like a,接口中定义的是扩展功能。(比如猫像运动员一样跳……)
18:形式参数和返回值的问题
(1)形式参数:
类名:需要该类的对象
抽象类名:需要该类的子类对象
接口名:需要该接口的实现类对象
(2)返回值类型:
类名:返回的是该类的对象
抽象类名:返回的是该类的子类对象
接口名:返回的是该接口的实现类的对象
(3)链式编程
对象.方法1().方法2().......方法n();
这种用法:其实在方法1()调用完毕后,应该返回一个对象;
方法2()调用完毕后,也应该返回一个对象。
方法n()调用完毕后,可能是对象,也可以不是对象,最后无所谓咯。
19:包
(1)其实就是文件夹
(2)作用:A:区分同名的类
B:对类进行分类管理: a:按照功能分 b:按照模块分
(3)包的定义:package 包名; 多级包用.分开。
(4)注意事项:A:package语句必须在文件中的第一条有效语句
B:在一个java文件中,只能有一个package
C:如果没有package,默认就是无包名
(5)带包的编译和运行
A:手动式 (DOS命令中javac -d . HelloWorld.java)
B:自动式(导包)
导包: a:关键字import。
b:格式:import 包名...类名;另一种:import 包名...*;(不建议)
c:package,import,class的顺序: package > import > class
20:修饰符
(1)权限修饰符: private:本类的能用
默认 :一个包里的能用
Protected:所有子类能用
public :最高级
这四种权限修饰符在任意时刻只能出现一种。
(2)常见的类及其组成的修饰
类:默认,public,final,abstract 常用的:public
成员变量:private,默认,protected,public,static,final 常用的:private
构造方法:private,默认,protected,public 常用的:public
成员方法:private,默认,protected,public,static,final,abstract 常用的:public
(3)另外比较常见的:
public static final int X = 10;
public static void show() {}
public final void show() {}
public abstract void show();
21:内部类
(1)把类定义在另一个类的内部,该类就被称为内部类。
(2)内部类的访问规则
A:可以直接访问外部类的成员,包括私有
B:外部类要想访问内部类成员,必须创建对象
(3)内部类的分类
A:成员内部类
B:局部内部类
(4)成员内部类
A:private 为了数据的安全性
B:static 为了访问的方便性
成员内部类不是静态的:
外部类名.内部类名 对象名 = new 外部类名.new 内部类名();
成员内部类是静态的:
外部类名.内部类名 对象名 = new 外部类名.内部类名(); (这里前面的类名对后面的类名起到限定作用。)
成员内部类和外部类没有继承关系。
(5)局部内部类
A:局部内部类访问局部变量必须加final修饰。
B:为什么呢?
因为局部变量使用完毕就消失,而堆内存的数据并不会立即消失。
所以,堆内存还是用该变量,而改变量已经没有了。
为了让该值还存在,就加final修饰。
通过反编译工具我们看到了,加入final后,堆内存直接存储的是值,而不是变量名。
class Outer { private int num = 10; public void method() { final int num2 = 20;注意这个在局部类外 class Inner { public void show() { System.out.println(num);A:可以直接访问外部类的成员 System.out.println(num2); } } Inner i = new Inner();B:在局部位置,可以创建内部类对象,通过i.show();对象调用内部类方法,来使用局部内部类功能 } } class InnerClassDemo5 { public static void main(String[] args) { Outer o = new Outer(); o.method(); } }
(6)匿名内部类
A:是局部内部类的简化形式
B:前提:存在一个类或者接口
C:格式:
new 类名或者接口名() {
重写方法;
}
D:本质:其实是继承该类或者实现接口的子类匿名对象
(7)匿名内部类在开发中的使用
我们在开发的时候,会看到抽象类,或者接口作为参数。
而这个时候,我们知道实际需要的是一个子类对象。
如果该方法仅仅调用一次,我们就可以使用匿名内部类的格式简化。
interface Person { public abstract void study(); } class PersonDemo { public void method(Person p) { p.study(); } } class PersonTest { public static void main(String[] args) { PersonDemo pd = new PersonDemo(); pd.method(new Person() { public void study() { System.out.println("好好学习,天天向上"); } }); } }
22:Scanner
(1)基本方法格式:
A:hasNextXxx() 判断是否是某种类型的
B:nextXxx() 返回某种类型的元素
(2)注意
A:同一个Scanner对象,先获取数值,再获取字符串会出现一个小问题。
B:解决方案:
a:重新定义一个Scanner对象
b:把所有的数据都用字符串获取,然后再进行相应的转换
常用类和集合框架
一 常用类
1:Object类
(1)Object是类层次结构的根类,所有的类都直接或者间接的继承自Object类。
(2)Object类的构造方法有一个,并且是无参构造
这其实就是理解当时我们说过,子类构造方法默认访问父类的构造是无参构造
(3)方法(掌握):
A:toString()
返回对象的字符串表示,默认是由类的全路径+'@'+哈希值的十六进制表示。
这个表示其实是没有意义的,一般子类都会重写该方法。
B:equals()
比较两个对象是否相同。默认情况下,比较的是地址值是否相同。
而String类重写了该方法,比较大的内容是否相同。
(4)方法(了解):
A:hashCode() 返回对象的哈希值。不是实际地址值,可以理解为地址值。
B:getClass() 返回对象的字节码文件对象,反射中我们会详细讲解
C:finalize() 用于垃圾回收,在不确定的时间
D:clone() 可以实现对象的克隆,包括成员变量的数据复制,需要Cloneable接口,举个例子:TestClone tc2=(TestClone) tc1.clone();
(5)两个注意问题;
A:直接输出一个对象名称,其实默认调用了该对象的toString()方法。
B:面试题
==和equals()的区别?
A:==
基本类型:比较的是值是否相同
引用类型:比较的是地址值是否相同
B:equals()
只能比较引用类型。
2:String类
(1)多个字符组成的一串数据。其实它可以和字符数组进行相互转换。
(2)构造方法:
A:public String()
B:public String(byte[] bytes)
C:public String(byte[] bytes,int offset,int length)
D:public String(char[] value)
E:public String(char[] value,int offset,int count)
F:public String(String original)
G:String s = "hello";(这个虽然不是构造方法,但是结果也是一个字符串对象)
(3)特点
A:字符串一旦创建就不能更改。即便使用替换方法,实际上是重新创建了一个String对象,原有对象依然存在。
B:字面值作为字符串对象和通过构造方法创建对象的不同
String s = new String("hello");和String s = "hello"的区别。前者从栈指向堆有一个地址值,堆指向方法区的字符串常量池又是一个地址值,这个地址值是 后者从栈直接指向方法区的字符串常量池的地址值。(例子如下)
(4)面试题(看程序写结果)
A:==和equals()
String s3 = new String("hello"); String s4 = "hello"; System.out.println(s3 == s4);// false System.out.println(s3.equals(s4));// true String s5 = "hello"; String s6 = "hello"; System.out.println(s5 == s6);// true System.out.println(s5.equals(s6));// true
B:字符串的拼接
String s1 = "hello"; String s2 = "world"; String s3 = "helloworld"; System.out.println(s3 == s1 + s2);// false System.out.println(s3.equals((s1 + s2)));// true System.out.println(s3 == "hello" + "world");// true(这种比较现在方法区找,没有的话再在方法区里创建) System.out.println(s3.equals("hello" + "world"));// true
(5)字符串的功能
A:判断功能
boolean equals(Object obj) boolean equalsIgnoreCase(String str) boolean contains(String str) boolean startsWith(String str) boolean endsWith(String str) boolean isEmpty()
B:获取功能
int length() char charAt(int index) int indexOf(int ch) int indexOf(String str) int indexOf(int ch,int fromIndex) int indexOf(String str,int fromIndex) String substring(int start) String substring(int start,int end)
C:转换功能
byte[] getBytes() char[] toCharArray() static String valueOf(char[] chs) static String valueOf(int i) String toLowerCase() String toUpperCase() String concat(String str)
D:其他功能
a:替换功能
String replace(char old,char new)
String replace(String old,String new)
b:去空格功能
String trim()
c:按字典比较功能
int compareTo(String str)
int compareToIgnoreCase(String str)
3:StringBuffer
(1)字符串拼接耗时耗内存,Java就提供了字符串缓冲区类——StringBuffer
(2)StringBuffer的构造方法
A:StringBuffer()
B:StringBuffer(int size)
C:StringBuffer(String str)
(3)StringBuffer的常见功能
A:添加功能
public StringBuffer append(String str)
public StringBuffer append(String str)
B:删除功能
public StringBuffer deleteCharAt(int index)
public StringBuffer delete(int start,int end)
C:替换功能
public StringBuffer replace(int start,int end,String str)
D:反转功能
public StringBuffer reverse()
E:截取功能(注意这个返回值是String类型)
public String substring(int start)
public String substring(int start,int end)
4:Integer
(1)为了让基本类型的数据进行更多的操作,Java就为每种基本类型提供了对应的包装类类型
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean
(2)Integer的构造方法
A:Integer i = new Integer(100);
B:Integer i = new Integer("100");
注意:这里的字符串必须是由数字字符组成(相应格式)
包装类转为基本类型:对象名.基本数据类型Value();
字符串转为包装类:包装类类名.valueOf(String str);
(3)String和int的相互转换
A:String -- int Integer.parseInt("100");
B:int -- String String.valueOf(100);
(4)JDK5的新特性
自动装箱 基本类型--引用类型
自动拆箱 引用类型--基本类型
例: Integer i = 100;
i += 200;(先做自动拆箱,再自动装箱)
(5)面试题:-128到127之间的数据缓冲池问题(超出范围就创建新的地址)
5:Character
(1)Character构造方法
Character ch = new Character('a');
(2)方法
A:判断给定的字符是否是大写public static boolean isUpperCase(char ch)
B:判断给定的字符是否是小写public static boolean isLowerCase(char ch)
C:判断给定的字符是否是数字字符public static boolean isDigit(char ch)
D:把给定的字符转成大写public static char toUpperCase(char ch)
E:把给定的字符转成小写public static char toLowerCase(char ch)
6:Math
(1)针对数学运算进行操作的类
(2)常见方法
A:绝对值public static int abs(int a)
B:向上取整public static double ceil(double a)
C:向下取整public static double floor(double a)
D:两个数据中的大值public static int max(int a,int b)
E:a的b次幂public static double pow(double a,double b)
F:随机数public static double random()
G:四舍五入public static int round(float a)
H:正平方根public static double sqrt(double a)
7:Random
(1)用于产生随机数的类
(2)构造方法:
A:Random() 默认种子,每次产生的随机数不同
B:Random(long seed) 指定种子,每次种子相同,随机数就相同
(3)成员方法:
A:int nextInt() 返回int范围内的随机数
B:int nextInt(int n) 返回[0,n)范围内的随机数
8:System
(1)系统类,提供了一些有用的字段和方法
(2)成员方法
A:运行垃圾回收器public static void gc()
B:退出jvm public static void exit(int status) (status为0)
C:获取当前时间的毫秒值public static long currentTimeMillis()
D:数组复制public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length) (书上有p191)
9:BigInteger
(1)针对大整数的运算
(2)构造方法
A:BigInteger(String s)
(3)成员方法
A:加public BigInteger add(BigInteger val)
B:减public BigInteger subtract(BigInteger val)
C:乘public BigInteger multiply(BigInteger val)
D:除public BigInteger divide(BigInteger val)
E:商和余public BigInteger[] divideAndRemainder(BigInteger val):返回商和余数的数组 例: BigInteger[] bis = bi1.divideAndRemainder(bi2);
System.out.println("商:" + bis[0]);
System.out.println("余数:" + bis[1]);
10:BigDecimal
(1)浮点数据做运算,会丢失精度。所以,针对浮点数据的操作建议采用BigDecimal。 (金融相关的项目)
(2)构造方法
A:BigDecimal(String s)
(3)成员方法:
A:加public BigDecimal add(BigDecimal augend)
B:减public BigDecimal subtract(BigDecimal subtrahend)
C:乘public BigDecimal multiply(BigDecimal multiplicand)
D:除public BigDecimal divide(BigDecimal divisor)
E:自己保留小数几位public BigDecimal divide(BigDecimal divisor,int scale,int roundingMode) 商,几位小数,如何舍取
11:Date/DateFormat
(1)Date是日期类,可以精确到毫秒。
A:构造方法
Date()
Date(long time)
B:成员方法
getTime()
setTime(long time)
C:日期和毫秒值的相互转换
(2)DateFormat针对日期进行格式化和针对字符串进行解析的类,但是是抽象类,所以使用其子类SimpleDateFormat
A:SimpleDateFormat(String pattern) 给定模式
yyyy-MM-dd HH:mm:ss
B:日期和字符串的转换
a:日期转为字符串(格式化) format()
例: Date d=new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); String s = sdf.format(d);
b:字符串转为日期(解析) parse()
例: String str = "2008-08-08 12:12:12"; //在把一个字符串解析为日期的时候,请注意格式必须和给定的字符串格式匹配 SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date dd = sdf2.parse(str);
12:Calendar
(1)日历类,封装了所有的日历字段值,通过统一的方法根据传入不同的日历字段可以获取值。
(2)如何得到一个日历对象呢?
Calendar rightNow = Calendar.getInstance(); (本质返回的是子类对象)
(3)成员方法
A:根据日历字段得到对应的值。如int year = rightNow.get(Calendar.YEAR);
B:根据日历字段和一个正负数确定是添加还是减去对应日历字段的值
如
// 5年后的10天前 c.add(Calendar.YEAR, 5); c.add(Calendar.DATE, -10); // 获取年 year = c.get(Calendar.YEAR); // 获取月 month = c.get(Calendar.MONTH); // 获取日 date = c.get(Calendar.DATE); System.out.println(year + "年" + (month + 1) + "月" + date + "日");
C:设置日历对象的年月日
如
c.set(2011, 11, 11); // 获取年 year = c.get(Calendar.YEAR); // 获取月 month = c.get(Calendar.MONTH); // 获取日 date = c.get(Calendar.DATE); System.out.println(year + "年" + (month + 1) + "月" + date + "日");
13:正则表达式
(1)就是符合一定规则的字符串
(2)常见规则
A:字符
x 字符 x。举例:'a'表示字符a
\ 反斜线字符。
新行(换行)符 ('u000A')
回车符 ('u000D')
B:字符类
[abc] a、b 或 c(简单类)
[^abc] 任何字符,除了 a、b 或 c(否定)
[a-zA-Z] a到 z 或 A到 Z,两头的字母包括在内(范围)
[0-9] 0到9的字符都包括
C:预定义字符类
. 任何字符。我的就是.字符本身,怎么表示呢? .
d 数字:[0-9]
w 单词字符:[a-zA-Z_0-9]
在正则表达式里面组成单词的东西必须有这些东西组成
D:边界匹配器
^ 行的开头
$ 行的结尾
单词边界
就是不是单词字符的地方。
举例:hello world?haha;xixi
E:Greedy 数量词
X? X,一次或一次也没有
X* X,零次或多次
X+ X,一次或多次
X{n} X,恰好 n 次
X{n,} X,至少 n 次
X{n,m} X,至少 n 次,但是不超过 m 次
(3)常见功能:
A:判断功能
String类的public boolean matches(String regex)
B:分割功能
String类的public String[] split(String regex)
C:替换功能
String类的public String replaceAll(String regex,String replacement)
D:获取功能
Pattern和Matcher
Pattern p = Pattern.compile("a*b");
Matcher m = p.matcher("aaaaab");
find():查找存不存在
group():获取刚才查找过的数据
集合框架
集合的使用步骤:
A:创建集合对象
B:创建元素对象
C:把元素添加到集合
D:遍历集合:
a:通过集合对象获取迭代器对象(对象名.iterator)
b:通过迭代器对象的hasNext()方法判断是否有元素
c:通过迭代器对象的next()方法获取元素并移动到下一个位置
1:对象数组
数组既可以存储基本数据类型,也可以存储引用类型。它存储引用类型的时候的数组就叫对象数组。
2:集合(Collection)
(1)数组的长度固定,所以不适合做变化的需求,Java就提供了集合。
(2)集合和数组的区别?
A:长度区别:数组固定;集合可变
B:内容区别:数组可以是基本类型,也可以是引用类型;集合只能是引用类型
C:元素内容:数组只能存储同一种类型;
集合可以存储不同类型(其实集合一般存储的也是同一种类型)
(3)集合的继承体系结构?
由于需求不同,Java就提供了不同的集合类。这多个集合类的数据结构不同,但是它们都是要提供存储和遍历功能的,我们把它们的共性不断的向上提取,最终就形成了集合的继承体系结构图。
Collection(接口)
|--List(接口)
|--ArrayList
|--Vector
|--LinkedList
|--Set(接口)
|--HashSet
|--TreeSet
(4)Collection的功能概述
A:添加功能
boolean add(Object obj):添加一个元素
boolean addAll(Collection c):添加一个集合的元素
B:删除功能
void clear():移除所有元素
boolean remove(Object o):移除一个元素
boolean removeAll(Collection c):移除一个集合的元素(是一个还是所有)
C:判断功能
boolean contains(Object o):判断集合中是否包含指定的元素
boolean containsAll(Collection c):判断集合中是否包含指定的集合元素(是一个还是所有)
boolean isEmpty():判断集合是否为空
D:获取功能
Iterator<E> iterator()(重点)
E:长度功能
int size():元素的个数
(5)Collection集合的遍历
迭代器(集合专用方式)是集合的获取元素的方式。是依赖于集合而存在的。
3:集合(List)
(1)List是Collection的子接口
特点:有序(存储顺序和取出顺序一致),可重复。
(2)List的特有功能:
A:添加功能void add(int index,Object element):在指定位置添加元素
B:删除功能Object remove(int index):根据索引删除元素,返回被删除的元素
C:获取功能Object get(int index):获取指定位置的元素
D:迭代器功能ListIterator listIterator():List集合特有的迭代器
E:修改功能Object set(int index,Object element):根据索引修改元素,返被修饰的元素
(3)List集合的特有遍历功能:由size()和get()结合。
for(int x=0; x<list.size(); x++) { String s =(String) list.get(x); System.out.println(s); }
(4)列表迭代器的特有功能;
可以逆向遍历,但是要先正向遍历,所以无意义,基本不使用。
(5)并发修改异常 ConcurrentModificationException:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。
A:出现的现象:迭代器遍历集合,集合修改集合元素
B:原因:迭代器是依赖于集合的,而集合的改变迭代器并不知道。
C:解决方案
a:迭代器遍历,迭代器修改(ListIterator)——元素跟在刚才迭代的元素后面
b:集合遍历,集合修改(size()和get())——元素添加在集合的末尾
(6)常见数据结构
A:栈 先进后出
B:队列 先进先出
C:数组 查询快,增删慢
D:链表 查询慢,增删快
(7)List的子类特点(面试题)
ArrayList
底层数据结构是数组,查询快,增删慢。
线程不安全,效率高。
Vector
底层数据结构是数组,查询快,增删慢。
线程安全,效率低。(因为线程安全,所以不太快,它已被ArrayList替代)
LinkedList
底层数据结构是链表,查询慢,增删快。
线程不安全,效率高。
(8):List的子类注意点
A:去除集合中的多个字符串的重复元素
如果字符串的内容相同,即为重复元素
B:去除集合中的多个自定义对象的重复元素
如果自定义对象的成员变量值都相同,即为重复元素(在source重写 equals方法即可)
C:用LinkedList模拟一个栈数据结构的集合类,并测试。
你要定义一个集合类,只不过内部可以使用LinkedList来实现。
4:泛型
(1)泛型概述
是一种把明确类型的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型。
(2)格式:
<数据类型> 注意:该数据类型只能是引用类型。(包装类是基本数据类型的引用类型)
(3)好处:
A:把运行时期的问题提前到了编译期间
B:避免了强制类型转换
C:优化了程序设计,解决了黄色警告线问题,让程序更安全
(4)泛型的前世今生
A:泛型的由来Object类型作为任意类型的时候,在向下转型的时候,会隐含一个转型问题
B:泛型类
C:泛型方法
D:泛型接口
E:泛型高级通配符
例: class Animal {} class Dog extends Animal {} // 泛型如果明确的写的时候,前后必须一致 Collection<Object> c1 = new ArrayList<Object>(); // ?表示任意的类型都是可以的 Collection<?> c7 = new ArrayList<Dog>(); // ? extends E:向下限定,E及其子类 Collection<? extends Animal> c11 = new ArrayList<Dog>();(Dog就是?) // ? super E:向上限定,E极其父类 Collection<? super Animal> c13 = new ArrayList<Object>();(Object是Animal父类) Collection<? super Animal> c14 = new ArrayList<Animal>();(本身满足条件,向下同理)
5:foreach
简化了数组和集合的遍历
6:静态导入(了解)
(1)可以导入到方法级别的导入
(2)格式:import static 包名....类名.方法名;
(3)注意事项:
A:方法必须是静态的
B:如果多个类下有同名的方法,就不好区分了,还得加上前缀。
7:可变参数
(1)如果我们在写方法的时候,参数个数不明确,就应该定义可变参数。
(2)格式:
修饰符 返回值类型 方法名(数据类型... 变量) {}
实例如下:
public static int sum(int... a) { int s = 0; for(int x : a){ s +=x; } return s; }
注意:
A:该变量其实是一个数组名
B:如果一个方法有多个参数,并且有可变参数,可变参数必须在最后
(3)Arrays工具类的一个方法
asList()把数组转成集合。
例:String[] strArray = { "hello", "world", "java" };
List<String> list = Arrays.asList(strArray);
或List<String> list = Arrays.asList("hello", "world", "java"); (集合转数组是toArray()方法)
注意:这个集合的长度不能改变。即使用add()、remove()修改长度会报错;UnsupportedOperationException
8:Set集合
(1)Set集合的特点:无序,唯一
(2)HashSet集合
A:底层数据结构是哈希表(是一个元素为链表的数组)
B:哈希表底层依赖两个方法:hashCode()和equals()
执行顺序:
首先比较哈希值是否相同
相同:继续执行equals()方法
返回true:元素重复了,不添加
返回false:直接把元素添加到集合
不同:就直接把元素添加到集合
C:如何保证元素唯一性的呢: 由hashCode()和equals()保证的
D:开发的时候,代码非常的简单,自动生成即可。(一般是创建类,让他实现comparable接口,要是需要具体比较的话,就按照下面例子重写compareTo方法)
E:HashSet存储字符串并遍历
F:HashSet存储自定义对象并遍历(对象的成员变量值相同即为同一个元素)
(3)TreeSet集合
A:底层数据结构是红黑树(是一个自平衡的二叉树)
B:保证元素的排序方式
a:自然排序(元素具备比较性)
让元素所属的类实现Comparable接口(下面是个排除信息重复的案例……也可以叫排序吧)
实例如下:
public class Student implements Comparable<Student> {}//泛型要写对应的类 @Override//然后重写接口方法,具体情况根据需求来写,下面只是个例子 public int compareTo(Student s) { // 主要条件 姓名的长度 int num = this.name.length() - s.name.length(); // 姓名的长度相同,不代表姓名的内容相同 int num2 = num == 0 ? this.name.compareTo(s.name) : num; // 姓名的长度和内容相同,不代表年龄相同,所以还得继续判断年龄 int num3 = num2 == 0 ? this.age - s.age : num2; return num3; }
b:比较器排序(集合具备比较性)
让集合构造方法接收Comparator的实现类对象
实例如下:
// 如果一个方法的参数是接口,那么真正要的是接口的实现类的对象 // 而匿名内部类就可以实现这个东西 TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() { @Override public int compare(Student s1, Student s2) { // 姓名长度 int num = s1.getName().length() - s2.getName().length(); // 姓名内容 int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num; // 年龄 int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2; return num3; } });
9:Collection集合总结
|--List 有序,可重复
|--ArrayList
底层数据结构是数组,查询快,增删慢。
线程不安全,效率高
|--Vector
底层数据结构是数组,查询快,增删慢。
线程安全,效率低
|--LinkedList
底层数据结构是链表,查询慢,增删快。
线程不安全,效率高
|--Set 无序,唯一
|--HashSet
底层数据结构是哈希表。
如何保证元素唯一性的呢?
依赖两个方法:hashCode()和equals()
开发中自动生成这两个方法即可
|--LinkedHashSet
底层数据结构是链表和哈希表
由链表保证元素有序
由哈希表保证元素唯一
|--TreeSet
底层数据结构是红黑树。
如何保证元素排序的呢?
自然排序
比较器排序
如何保证元素唯一性的呢?
根据比较的返回值是否是0来决定
针对Collection集合我们到底使用谁呢?
唯一吗?
是:Set
排序吗?
是:TreeSet
否:HashSet
如果你知道是Set,但是不知道是哪个Set,就用HashSet。
否:List
要安全吗?
是:Vector
否:ArrayList或者LinkedList
查询多:ArrayList
增删多:LinkedList
如果你知道是List,但是不知道是哪个List,就用ArrayList。
如果你知道是Collection集合,但是不知道使用谁,就用ArrayList。
如果你知道用集合,就用ArrayList。
在集合中常见的数据结构:
ArrayXxx:底层数据结构是数组,查询快,增删慢
LinkedXxx:底层数据结构是链表,查询慢,增删快
HashXxx:底层数据结构是哈希表。依赖两个方法:hashCode()和equals()
TreeXxx:底层数据结构是二叉树。两种方式排序:自然排序和比较器排序
10:Map
(1)将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
(2)Map和Collection的区别?
A:Map 存储的是键值对形式的元素,键唯一,值可以重复。
B:Collection 存储的是单独出现的元素,子接口Set元素唯一,子接口List元素可重复。
(3)Map接口功能概述
A:添加功能V put(K key,V value)
B:删除功能V remove(Object key)
C:判断功能boolean containsKey(Object key) boolean isEmpty()
D:获取功能V get(Object key)
Set<K> keySet()
Collection<V> values()
Set<Map.Entry<K,V>> entrySet()
E:长度功能int size()
(4)Map集合的遍历
A:键找值
a:获取所有键的集合
b:遍历键的集合,得到每一个键
c:根据键到集合中去找值
B:键值对对象找键和值
a:获取所有的键值对对象的集合
b:遍历键值对对象的集合,获取每一个键值对对象
c:根据键值对对象去获取键和值
代码体现:
Map<String,String> hm = new HashMap<String,String>(); hm.put("it002","hello"); hm.put("it003","world"); hm.put("it001","java"); //方式1 键找值 Set<String> set = hm.keySet(); for(String key : set) { String value = hm.get(key); System.out.println(key+"---"+value); } //方式2 键值对对象找键和值 Set<Map.Entry<String,String>> set2 = hm.entrySet(); for(Map.Entry<String,String> me : set2) { String key = me.getKey(); String value = me.getValue(); System.out.println(key+"---"+value); }
(5)HashMap集合的练习
A:HashMap<String,String>
B:HashMap<Integer,String>
C:HashMap<String,Student>
D:HashMap<Student,String>
(6)TreeMap集合的练习
A:TreeMap<String,String>
B:TreeMap<Student,String>
(7)案例
A:统计一个字符串中每个字符出现的次数
B:集合的嵌套遍历
a:HashMap嵌套HashMap
b:HashMap嵌套ArrayList
c:ArrayList嵌套HashMap
d:多层嵌套
11:Collections
(1)是针对集合进行操作的工具类
(2)面试题:Collection和Collections的区别
A:Collection 是单列集合的顶层接口,有两个子接口List和Set
B:Collections 是针对集合进行操作的工具类,可以对集合进行排序和查找等
(3)常见的几个小方法:(此类只针对List对象能用排序和乱序)
A:public static <T> void sort(List<T> list)
B:public static <T> int binarySearch(List<?> list,T key)
C:public static <T> T max(Collection<?> coll)
D:public static void reverse(List<?> list)
E:public static void shuffle(List<?> list)乱序
IO流
一
1:异常
(1)程序出现的不正常的情况。
(2)异常的体系
Throwable
|--Error 严重问题,我们不处理。
|--Exception
|--RuntimeException 运行期异常,我们需要修正代码
|--非RuntimeException 编译期异常,必须处理的,否则程序编译不通过
(3)异常的处理:
A:JVM的默认处理
把异常的名称,原因,位置等信息输出在控制台,但是呢程序不能继续执行了。
B:自己处理
a:try...catch...finally
自己编写处理代码,后面的程序可以继续执行
(初始化变量的作用域是大括号里面,所以可以在try的大括号外面进行变量初始化 如 :
Date d=null;
try{d=sdf.parse(s);}...)
b:throws
把自己处理不了的,在方法上声明,告诉调用者,这里有问题
(4)面试题
A:编译期异常和运行期异常的区别?(看throws后面的异常类型)
编译期异常 必须要处理的,否则编译不通过
运行期异常 可以不处理,也可以处理
B:throw和throws是的区别
throws用在方法声明后面,跟的是异常类名
可以跟多个异常类名,用逗号隔开
表示抛出异常,由该方法的调用者来处理
表示出现异常的一种可能性,并不一定会发生这些异常
throw用在方法体内,跟的是异常对象名(如 throw new ArithmeticException();),
只能抛出一个异常对象名
表示抛出异常,由方法体内的语句处理
表示抛出了异常,执行throw则一定抛出了某种异常
原则:如果该功能内部可以将问题处理,用try,如果处理不了,交由调用者处理,这是用throws
区别:后续程序需要继续运行就try,不需要继续运行就throws
(5)finally关键字及其面试题
A:finally用于释放资源,它的代码永远会执行。特殊情况:在执行到finally之前jvm退出了
B:面试题
如果在catch里面有return, finally还执行,并且在return前(实际上在中间)。
C:异常处理的变形
try...catch...finally
try...catch...
try...catch...catch...
try...catch...catch...fianlly
try...finally
(6)自定义异常
继承自Exception或者RuntimeException,只需要提供无参构造和一个带参构造即可
(带参要super(message);) public class Teacher { public void check(int score) throws MyException { if (score > 100 || score < 0) { throw new MyException("分数必须在0-100之间"); } else { System.out.println("分数没有问题"); } } // 针对MyException继承自RuntimeException,这个就不用throws // public void check(int score) { // if (score > 100 || score < 0) { // throw new MyException(); // } else { // System.out.println("分数没有问题"); // } // } }
(7)异常的注意实现
A:父的方法有异常抛出,子的重写方法在抛出异常的时候必须要小于等于父的异常
B:父的方法没有异常抛出,子的重写方法不能有异常抛出
C:父的方法抛出多个异常,子的重写方法必须比父少或者小
2:File
(1)IO流操作中大部分都是对文件的操作,所以Java就提供了File类供我们来操作文件
(2)构造方法
A:File file = new File("e:\demo\a.txt");(常用此方法)
B:File file = new File("e:\demo","a.txt");
C:File file = new File("e:\demo");
File file2 = new File(file,"a.txt");
(3)File类的功能
A:创建功能
public boolean createNewFile()
public boolean mkdir()
public boolean mkdirs()
B:删除功能
public boolean delete()
注意: a:如果你创建文件或者文件夹忘了写盘符路径,那么,默认在项目路径下。
b:Java中的删除不走回收站。
c:要删除一个文件夹,请注意该文件夹内不能包含文件或者文件夹
C:重命名功能
public boolean renameTo(File dest)(新名字也要建个对象)
注意:如果路径名相同,就是改名。
如果路径名不同,就是改名并剪切。
D:判断功能
public boolean isDirectory()(是否是根目录)
public boolean isFile()
public boolean exists()
public boolean canRead()
public boolean canWrite()
public boolean isHidden()
E:获取功能
public String getAbsolutePath()
public String getPath()(相对项目而言的路径)
public String getName()(文件名)
public long length()(字节大小)
public long lastModified()(获取最后修改时间毫秒值)
F:高级获取功能
public String[] list()获取指定目录下的所有文件或者文件夹的名称数组
public File[] listFiles()获取指定目录下的所有文件或者文件夹的File数组
G:过滤器功能
public String[] list(FilenameFilter filter)
public File[] listFiles(FilenameFilter filter)
(跟集合排序一样,方法返回值类型是接口,实际需要实现该接口的对象)
实例如下:
String[] sss=f4.list(new FilenameFilter() { @Override public boolean accept(File dir, String name) { File f=new File(dir,name); boolean flag=f.isFile(); boolean flag2=f.getName().endWith(".java"); return flag&&flag2; //或return new File(dir,name).isFile()&&name.endsWith(".java"); } });
(4)案例:
A:输出指定目录下指定后缀名的文件名称
a:先获取所有的,在遍历的时候判断,再输出
b:先判断,再获取,最后直接遍历输出即可
B:批量修改文件名称(难道不能修改文件夹名字吗?)
3:递归
(1)方法定义中调用方法本身的现象
找到出口条件,找到规律,加在一起就是递归方法了。
(2)递归的注意事项;
A:要有出口,否则就是死递归
B:次数不能过多,否则内存溢出
C:构造方法不能递归使用
(3)递归的案例:
A:递归输出指定目录下所有指定后缀名的文件绝对路径
步骤分析:
a:封装目录
b:获取该目录下所有的文件或者文件夹的File数组
c:遍历该File数组,得到每一个File对象
d:判断该File对象是否是文件夹
是:回到B
否:继续判断是否以.java结尾
是:就输出该文件的绝对路径
否:不搭理它
B:递归删除带内容的目录(小心使用)
步骤分析:
a:封装目录
b:获取该目录下的所有文件或者文件夹的File数组
c:遍历该File数组,得到每一个File对象
d:判断该File对象是否是文件夹
是:回到B
否:就删除
删文件夹的话需要文件夹为空,在循环外直接删就行。
二
1:IO流
(1)IO用于在设备间进行数据传输的操作
(2)分类:
A:流向
输入流 读取数据
输出流 写出数据
B:数据类型
字节流
字节输入流
字节输出流
字符流
字符输入流
字符输出流
IO流分类
字节流:
InputStream
FileInputStream
BufferedInputStream
OutputStream
FileOutputStream
BufferedOutputStream
字符流:
Reader
FileReader
BufferedReader
Writer
FileWriter
BufferedWriter
注意:
a:如果我们没有明确说明按照什么分,默认按照数据类型分。
b:除非文件用windows自带的记事本打开我们能够读懂,才采用字符流,否则建议使用字节流。
(3)FileOutputStream写出数据
A:操作步骤
a:创建字节输出流对象
b:调用write()方法
c:释放资源
B:代码体现:
FileOutputStream fos = new FileOutputStream("fos.txt");
fos.write("hello".getBytes());
fos.close();
C:要注意的问题?
a:创建字节输出流对象做了几件事情?
b:为什么要close()?
c:如何实现数据的换行?:不同的系统针对不同的换行符号识别是不一样的windows:
linux:
Mac:
而一些常见的个高级记事本,是可以识别任意换行符号的。
d:如何实现数据的追加写入?用构造方法带第二个参数是true的情况即可
(4)FileInputStream读取数据
A:操作步骤
a:创建字节输入流对象
b:调用read()方法
c:释放资源
B:代码体现:
FileInputStream fis = new FileInputStream("fos.txt"); //方式1 int by = 0; while((by=fis.read())!=-1) { System.out.print((char)by); } //方式2 byte[] bys = new byte[1024]; int len = 0; while((len=fis.read(bys))!=-1) { System.out.print(new String(bys,0,len)); } fis.close();
-
复制
FileInputStream fis=new FileInputStream("d:\t.txt"); FileOutputStream fos=new FileOutputStream("d:\a.txt"); int by=0; while((by=fis.read())!=-1){ fos.write(by); } fis.close(); fos.close();
复制文本文件图片视频方式一样,只换构造方法里的文件名即可。
注意:数据源和目的地的文件都存在才能复制,复制的是内容,文件都无法凭 空生成,要事先建好)
(6)字节缓冲区流
A:BufferedOutputStream(格式如下)
B:BufferedInputStream
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("t.txt"));
2:字符流
(1)字节流操作中文数据不是特别的方便,所以就出现了转换流。
转换流的作用就是把字节流转换字符流来使用。
(2)转换流其实是一个字符流
字符流 = 字节流 + 编码表
(3)编码表
A:就是由字符和对应的数值组成的一张表
B:常见的编码表
ASCII ISO-8859-1 GB2312 GBK GB18030 UTF-8
C:字符串中的编码问题
编码 String -- byte[]
解码 byte[] -- String
(4)IO流中的编码问题
A:OutputStreamWriter
OutputStreamWriter(OutputStream os):默认编码,GBK
OutputStreamWriter(OutputStream os,String charsetName):指定编码。
B:InputStreamReader
InputStreamReader(InputStream is):默认编码,GBK
InputStreamReader(InputStream is,String charsetName):指定编码
C:编码问题其实很简单: 编码只要一致即可
(5)字符流(字符流文件进了缓冲区,没写close时需要flush一下)
Reader
|--InputStreamReader
|--FileReader
|--BufferedReader
Writer
|--OutputStreamWriter
|--FileWriter
|--BufferedWriter(记得写flush和newLine)
(它们之间的关系:
BufferedWriter bw= new BufferedWriter (new OutputStreamWriter (new FileOutputStream (“bw.txt”));)
可以简化为BufferWriter bw =new BufferWriter(new FileWriter(“bw.txt”));)
3:IO流小结
IO流
|--字节流
|--字节输入流InputStream
int read():一次读取一个字节
int read(byte[] bys):一次读取一个字节数组
|--FileInputStream
|--BufferedInputStream
|--字节输出流OutputStream
void write(int by):一次写一个字节
void write(byte[] bys,int index,int len):一次写一个字节数组的部分
|--FileOutputStream
|--BufferedOutputStream
|--字符流
|--字符输入流Reader
int read():一次读取一个字符
int read(char[] chs):一次读取一个字符数组
|--InputStreamReader
|--FileReader
|--BufferedReader
String readLine():一次读取一个字符串
|--字符输出流Writer
void write(int ch):一次写一个字符
void write(char[] chs,int index,int len):一次写一个字符数组的一部分
|--OutputStreamWriter
|--FileWriter
|--BufferedWriter
void newLine():写一个换行符
void write(String line):一次写一个字符串
4数据操作流(操作基本类型数据的流)
(1)可以操作基本类型的数据
(2)流对象名称
DataInputStream
DataOutputStream
5:内存操作流
(1)有些时候我们操作完毕后,未必需要产生一个文件,就可以使用内存操作流。
(2)三种
A:ByteArrayInputStream,ByteArrayOutputStream
B:CharArrayReader,CharArrayWriter
C:StringReader,StringWriter
6:打印流
(1)字节打印流,字符打印流
(2)特点:
A:只操作目的地,不操作数据源
B:可以操作任意类型的数据
C:如果启用了自动刷新,在调用println()方法的时候,能够换行并刷新
D:可以直接操作文件
问题:哪些流可以直接操作文件呢?
看API,如果其构造方法能够同时接收File和String类型的参数,一般都是可以直接操作文件的
(3)复制文本文件
BufferedReader br = new BufferedReader(new FileReader("a.txt")); PrintWriter pw = new PrintWriter(new FileWriter("b.txt"),true); String line = null; while((line=br.readLine())!=null) { pw.println(line); } pw.close(); br.close();
7:标准输入输出流
(1)System类下面有这样的两个字段
in 标准输入流
out 标准输出流
(2)三种键盘录入方式
A:main方法的args接收参数
B:System.in通过BufferedReader进行包装
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
C:Scanner Scanner sc = new Scanner(System.in);
(3)输出语句的原理和如何使用字符流输出数据
A:原理
System.out.println("helloworld");
PrintStream ps = System.out;
ps.println("helloworld");
B:把System.out用字符缓冲流包装一下使用
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
8:随机访问流
(1)可以按照文件指针的位置写数据和读数据。
(2)案例:
A:写数据
B:读数据
C:获取和改变文件指针的位置
9:合并流
(1)把多个输入流的数据写到一个输出流中。
(2)构造方法:
A:SequenceInputStream(InputStream s1, InputStream s2)
B:SequenceInputStream(Enumeration<? extends InputStream> e)
10:序列化流
(1)可以把对象写入文本文件或者在网络中传输
(2)如何实现序列化呢?
让被序列化的对象所属类实现序列化接口。
该接口是一个标记接口。没有功能需要实现。
(3)注意问题:
把数据写到文件后,在去修改类会产生一个问题。
如何解决该问题呢?
在类文件中,给出一个固定的序列化id值。
而且,这样也可以解决黄色警告线问题
11:Properties
(1)是一个集合类,Hashtable的子类
(2)特有功能
A:public Object setProperty(String key,String value)
B:public String getProperty(String key)
C:public Set<String> stringPropertyNames()
(3)和IO流结合的方法
把键值对形式的文本文件内容加载到集合中
public void load(Reader reader)
public void load(InputStream inStream)
把集合中的数据存储到文本文件中
public void store(Writer writer,String comments)
public void store(OutputStream out,String comments)
(4)案例:
A:根据给定的文件判断是否有键为"lisi"的,如果有就修改其值为100
B:写一个程序实现控制猜数字小游戏程序不能玩超过5次
12:NIO
(1)JDK4出现的NIO,对以前的IO操作进行了优化,提供了效率。但是大部分我们看到的还是以前的IO
(2)JDK7的NIO的使用
Path:路径
Paths:通过静态方法返回一个路径
Files:提供了常见的功能
复制文本文件
把集合中的数据写到文本文件
多线程
1:多线程
(1)多线程:一个应用程序有多条执行路径
进程:正在执行的应用程序
线程:进程的执行单元,执行路径
单线程:一个应用程序只有一条执行路径
多线程:一个应用程序有多条执行路径
多进程的意义?提高CPU的使用率
多线程的意义?提高应用程序的使用率
(2)Java程序的运行原理及JVM的启动是多线程的吗?
A:Java命令去启动JVM,JVM会启动一个进程,该进程会启动一个主线程。
B:JVM的启动是多线程的,因为它最低有两个线程启动了,主线程和垃圾回收线程。
(3)多线程的实现方案(自己补齐步骤及代码 掌握)
A:继承Thread类
B:实现Runnable接口
(4)线程的调度和优先级问题
A:线程的调度
a:分时调度
b:抢占式调度 (Java采用的是该调度方式)
B:获取和设置线程优先级
a:默认是5
b:范围是1-10
(5)线程的控制(常见方法)
A:休眠线程
B:加入线程
C:礼让线程
D:后台线程
E:终止线程(掌握)当线程在活动之前或活动期间处于正在等待、休眠或占用状态,才能被中断,且抛出异常的catch语句,但剩下的继续执行完。
(6)线程的生命周期(参照 线程生命周期图解.bmp)
A:新建
B:就绪
C:运行
D:阻塞
E:死亡
(7)电影院卖票程序的实现
A:继承Thread类
B:实现Runnable接口
(8)电影院卖票程序出问题
A:为了更符合真实的场景,加入了休眠100毫秒。
B:卖票问题
a:同票多次
b:负数票
(9)多线程安全问题的原因(也是我们以后判断一个程序是否有线程安全问题的依据)
A:是否有多线程环境
B:是否有共享数据
C:是否有多条语句操作共享数据
同步解决线程安全问题
A:同步代码块
synchronized(对象) {
需要被同步的代码;
}
这里的锁对象可以是任意对象,在run方法外随便new一个,是大家共享的就行。
B:同步方法
把同步加在方法上。
这里的锁对象是this
C:静态同步方法
把同步加在方法上。
这里的锁对象是当前类的字节码文件对象(反射再讲字节码文件对象)
(11)回顾以前的线程安全的类
A:StringBuffer
B:Vector
C:Hashtable
D:如何把一个线程不安全的集合类变成一个线程安全的集合类
用Collections工具类的方法即可。
List<String> list2 = Collections.synchronizedList(new ArrayList<String>());
2:补充
(1)JDK5以后的针对线程的锁定操作和释放操作
Lock锁(用的不多)
格式:在run方法外创建Lock l=new ReentrantLock();然后
try{
l.lock();
要锁的方法
}finally{
l.unlock(); }
(2)死锁问题的描述和代码体现
(3)生产者和消费者多线程体现(线程间通信问题)
小知识点:如何让多个类共享同一个数据?答:在外界把这个数据创建出来,通过构造方法传递给其他的类。
资源类:Student
设置数据类:SetThread(生产者)
获取数据类:GetThread(消费者)
测试类:StudentDemo
代码:
A:最基本的版本,只有一个数据。
B:改进版本,给出了不同的数据,并加入了同步机制
C:等待唤醒机制改进该程序,让数据能够实现依次的出现
wait()
notify()
notifyAll() (多生产多消费)
D:等待唤醒机制的代码优化。把数据及操作都写在了资源类中
(4)线程组
创建格式:
// 构造方法ThreadGroup(String name)
ThreadGroup tg = new ThreadGroup("这是一个新的组"); MyRunnable my = new MyRunnable(); // Thread(ThreadGroup group, Runnable target, String name) Thread t1 = new Thread(tg, my, "林青霞"); Thread t2 = new Thread(tg, my, "刘意");
(5)线程池
创建格式:
// 创建一个线程池对象,控制要创建几个线程对象。 // public static ExecutorService newFixedThreadPool(int nThreads) ExecutorService pool = Executors.newFixedThreadPool(2); // 可以执行Runnable对象或者Callable对象代表的线程 pool.submit(new MyRunnable()); pool.submit(new MyRunnable()); //结束线程池 pool.shutdown();
3:设计模式
(1)面试对象的常见设计原则
单一
开闭
里氏
依赖注入
接口
迪米特
(2)设计模式概述和分类
A:经验的总结
B:三类
创建型
结构型
行为型
(3)改进的设计模式
A:简单工厂模式
B:工厂方法模式
C:单例模式(掌握)
饿汉式:类一加载就创建对象
懒汉式:用的时候,才去创建对象
开发:饿汉式(是不会出问题的单例模式)
面试:懒汉式(可能会出问题的单例模式)
A:懒加载(延迟加载)
B:线程安全问题
a:饿汉式
实例如下:public class Student { // 构造私有 private Student() {} // 自己造一个 / 静态方法只能访问静态成员变量,加静态 // 为了不让外界直接访问修改这个值,加private private static Student s = new Student(); // 提供公共的访问方式 // 为了保证外界能够直接使用该方法,加静态 public static Student getStudent() { return s; }
}
b:懒汉式
实例如下:public class Teacher { private Teacher() {} private static Teacher t = null; public synchronized static Teacher getTeacher() { if (t == null) { t = new Teacher(); } return t; } }
(4)Runtime
JDK提供的一个单例模式应用的类。
还可以调用dos命令。
实例如下:public static void main(String[] args) throws IOException { Runtime r = Runtime.getRuntime(); //r.exec("winmine"); // r.exec("notepad"); // r.exec("calc"); //r.exec("shutdown -s -t 10000"); r.exec("shutdown -a");
}
-
GUI
1:如何让Netbeans的东西Eclipse能访问。
在Eclipse中创建项目,把Netbeans项目的src下的东西给拿过来即可。注意:修改项目编码为UTF-8
2:GUI(了解)
(1)用户图形界面
GUI:方便直观
CLI:需要记忆一下命令,麻烦
(2)两个包:
java.awt:和系统关联较强
javax.swing:纯Java编写
(3)GUI的继承体系
组件:组件就是对象
容器组件:是可以存储基本组件和容器组件的组件。
基本组件:是可以使用的组件,但是必须依赖容器。
(4)事件监听机制(理解)
A:事件源
B:事件
C:事件处理
D:事件监听
(5)适配器模式(理解)
A:接口
B:抽象适配器类
C:实现类
(6)案例:
A:创建窗体案例
B:窗体关闭案例
C:窗体添加按钮并对按钮添加事件案例。
界面中的组件布局。
D:把文本框里面的数据转移到文本域
E:更改背景色
F:设置文本框里面不能输入非数字字符
G:一级菜单
H:多级菜单
(7)Netbeans的概述和使用
A:是可以做Java开发的另一个IDE工具。
B:使用
A:四则运算
a:修改图标
b:设置皮肤
c:设置居中
d:数据校验
B:登录注册
网络编程
1:网络编程
(1)网络编程:用Java语言实现计算机间数据的信息传递和资源共享
(2)网络编程模型
(3)网络编程的三要素
A:IP地址
a:点分十进制
b:IP地址的组成
c:IP地址的分类
d:dos命令
e:InetAddress
B:端口
是应用程序的标识。范围:0-65535。其中0-1024不建议使用。
C:协议
UDP:数据打包,有限制,不连接,效率高,不可靠
TCP:建立数据通道,无限制,效率低,可靠
(3)Socket机制
A:通信两端都应该有Socket对象
B:所有的通信都是通过Socket间的IO进行操作的
(4)UDP协议发送和接收数据(掌握 自己补齐代码)
发送:
创建UDP发送端的Socket对象
创建数据并把数据打包
发送数据
释放资源
接收:
创建UDP接收端的Socket对象
创建数据包用于接收数据
接收数据
解析数据包
释放资源
(5)TCP协议发送和接收数据(掌握 自己补齐代码)
发送:
创建TCP客户端的Socket对象
获取输出流,写数据
释放资源
接收:
创建TCP服务器端的Socket对象
监听客户端连接
获取输入流,读取数据
释放资源
(6)案例:
A:UDP
a:最基本的UDP协议发送和接收数据
b:把发送数据改进为键盘录入
c:一个简易聊天小程序并用多线程改进
B:TCP
a:最基本的TCP协议发送和接收数据
b:服务器给出反馈
c:客户端键盘录入服务器控制台输出
d:客户端键盘录入服务器写到文本文件
e:客户端读取文本文件服务器控制台输出
f:客户端读取文本文件服务器写到文本文件
g:上传图片
h:多线程改进上传文件
反射
1:反射
(1)类的加载及类加载器
(2)反射:
通过字节码文件对象,去使用成员变量,构造方法,成员方法
(3)反射的使用
A:通过反射获取构造方法并使用
B:通过反射获取成员变量并使用
C:通过反射获取成员方法并使用
(4)反射案例
A:通过反射运行配置文件的内容
B:通过反射越过泛型检查
C:通过反射给任意的一个对象的任意的属性赋值为指定的值
(5)动态代理
2:设计模式
(1)装饰设计模式
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
Scanner sc = new Scanner(System.in);
(2)模版设计模式
3:JDK新特性
(1)JDK5(掌握)
装箱和拆箱
泛型
增强for
静态导入
可变参数
枚举
(2)JDK6(了解)
(3)JDK7(理解)
二进制的表现形式
用_分隔数据
switch语句可是用字符串
泛型推断(菱形泛型)
多catch的使用
自动释放资源的用法
(4)JDK8(了解)