写代码:
1,明确需求。我要做什么? 分析的时候:从具体到抽象
2,分析思路。我要怎么做?1,2,3。 实现的时候:从抽象到具体
3,确定步骤。每一个思路部分用到哪些语句,方法,和对象。
4,代码实现。用具体的java语言代码把思路体现出来。
使用:使用具体类抽象类没有对应的具体类就用不了,它需要子类来实现
//写方法:1、明确返回值 2、明确参数列表
学习新技术的四点:
1,该技术是什么?
2,该技术有什么特点(使用注意):
3,该技术怎么使用。demo
4,该技术什么时候用?test。
====================================================================
快捷键:格式化:ctrl+shift+F 导包:ctrl+shift+O 查看方法说明:F2
内容提示:Alt+/ 快速修复代码:Alt+1 看源码:Alt+(左右键)
注释:单行ctrl + / 多行注释:ctrl+shift+/
查看源码:F3或者ctrl+鼠标点击 查看类的继承关系:ctrl+T
复制行:Ctrl+Alt+向下键 代码上下移动:Alt + /
更改为大写:ctrl+shift+X 更改为小写:ctrl+shift+Y
查看所有快捷键:ctrl+shift+L
重置透视图:window-perspctect-Resetperspctect
帮助文档生成:选中项目-右键-Export-java-Javadoc-Finish
导入项目:空白右键-improt-General-Existingprojects into Workspace
创建学生类:alt+shift+C alt+shift+O alt+shift+R
标准代码步骤:属性私有化;加访问器get、生成器set;复写toString;复写hashcode、equals
类名:全部单词首字母大写 DemoTest;
方法:getName;
可以包含26个字母,0-9,_,$
不可以数字开头;不能喝关键字同名
1 byte = 8 bit
1 K =1024 b
1 M = 1024 K
1 G = 1024 M
1 T = 1024 G
负数的二进制是整数的二进制取反+1;
负数的整数也是二进制取反+1;(二进制取反+1等价于-1再取反)
最高位:0表示正数,1表示负数
数据类型: A:决定变量占用多大的内存空间
B:决定了变量所存储了什么类型的数
整型:- byte一个字节(-128到127)
-short 两个字节(-32767到32768)
-int 4个字节
-long 8个字节
浮点型:
- float 4个字节
- double 8个字节
字符型:
-char2个字节
布尔型:boolean(true,false)1个字节
>> 右移,高位是什么就补什么
>>>无符号位移;高位无论是什么都补0
试试
对象:
面向对象的特征:封装、继承、多态
构造函数/方法是为了:初始化成员
对象中:把事物属性都为名词,把方法作为动词
对象之间采用“方法调用”来通信
重载的定义是:在一个类中,如果出现了两个或者两个以上的同名函数,只要它们的参数的个数,或者参数的类型不同,即可称之为该函数重载了。
如何区分重载:当函数同名时,只看参数列表。和返回值类型没关系。
面向对象的特征:封装,继承,多态
垃圾回收:不是回收对象,而是回收对象所占的内存。
一个类中:局部变量优先级大于成员变量
成员变量初始化:
1:初始化成员变量 2:
3:使用其属性的时候初始化/JAVA中称惰性初始化/Android叫延迟加载
基本数据类型:byte、short、int、long、float、double、char、boolean=
JAVA中内存分配:
栈 存储 局部变量:在方法定义中或方法,声明上的变量都是局部变量
堆 存储new出来的东西
方法区
本地方法区(和系统相关)
寄存器(CPU使用)
Obj instanceof Person:判断是不是属于Person类
数组:
实际参数:参与运算的参数
形式参数:定义在方法上的,用于接收实际参数
数组的定义格式:
动态初始化:
格式1: 数据类型[] 数组名; 格式2: 数据类型 数组名[];
int[]arr =new int[3];
syso(arr);//打印的是地址值
syso(arr[0]);
syso(arr[1]);
syso(arr[2]);
数组的静态初始化:
格式: 数据类型[] 数组名= new 数据类型[]{元素1,元素2,...}
简写格式: 数据类型[] 数组名 ={元素1,元素2,...};
例: int[] arr =new int[]{1,2,3};
数组简写格式为:int[] arr={1,2,3};
数组的长度: 数组名.length 返回数组长度(int)
数组的遍历: 输出形式为: [1,2,3,6,3]
System.out.print(“[”);
for(i=0;i<arr.length-1;i++){
If(i==arr.length-1){//如果是最后一个,输出i和括号
System.out.println(arr[i])+“]”; }
else{ //如果不是最后一行输出x和,
System.out.print(arr[x]+“,”); }
二维数组:
格式1:数据类型[][] 数组名 = new 数据类型[m][n];
m:表示这个二维数组有多少个一维数组
n:表示每个一位数组的元素有多少
格式2:数据类型[][] 数组名 = new 数据类型[m][];
m:表示这个二维数组有多少个一维数组
列数没有给出,可以动态的给,这一次是一个变化的列数
格式3*:数据类型[][] 数组名 = new 数据类型[元素…][元素…]{}{};
简化版:数据类型[][]数组名=new {{元素…}{元素…}{元素…}};
举例: int[][]arr = new {{1,2,3}{4,6}{7}};
坑爹题目:
int x,y 表示输入:int x, int y
int[] x 表示定义一个数组:int[] x
int[] x,y 表示定义两个数组:int[] x ;int[] y
int[] x,[]y 表示定义一个数组,一个二维数组:int[]x ; int [] [] y;
二维数组遍历:
for(int x=0;x<arr.length;x++){
f(inty =0;y<arr[x].length;y++){
syso(arr[x][y]+“ ”); }}
数组总结:
JAVA中的参数传递问题:
基本类型:形式参数的改变对实际参数没有影响。(数据传递:是数据值本身,传递时是副本在传递)
引用类型:形式参数的改变直接影响实际参数。 (数据传递是:地址值 )
匿名对象:
匿名对象即没有名字的对象。
应用场景:
A: 调用方法,仅仅调用一次的时候 !
注意:调用多次的时候,不合适。
好处:匿名对象调用完毕就是垃圾,可以被垃圾回收器回收
B: 匿名对象可以作为实际参数传递
Class Student{
publicvoid show(){
syso(“我爱学习”); }}
class StudentDemo{
publicvoid method(Student s){
s.show(); }}
class NoNameDemo{
publicstatic void main(String[] args){
//带名字的调用
Students=new Student();
s.show();
s.show();//一个对象调用第二次
//匿名对象
NewStudent().show();
New Student().show();//创建第二个对象,然后调用方法
//匿名对象作为实际参数传递
StudentDemosd =new StudentDemo();
//Studentss= new Student();
//sd.method(ss);//这里的s是一个实际参数 }}
sd.method(newStudent());
//多个匿名对象
newStudentDemo().method(new Student());
好处:隐藏对象的属性和实现细节,仅对外提供公共的访问方式提高代码复用性和安全性。
也可以在方法内添加校验!但是标准代码里不做校验:
get:访问器 读 set:变异器 写
Public int getXxx(){
return Xxx; } //getXxx,是获取值,所以要返回一个值
Public int setXxx(int x){
this.Xxx=Xxx; }//setXxx是要给属性赋值
this: 哪个对象调用,在该方法就代表哪个对象
应用场景: A:解决局部变量隐藏成员变量。放在构造方法第一行。
B:在非static的普通方法中调用该方法的对象(static方法里不能有this)
C:用于返回对象(链式编程)。
D:把this作为实际参数传递。
E:.public 类名+方法名()(链式编程) public Person add(){}
F:把this当做参数
例:public class Incream{
int index = 0;
public Incream add(){
index++;
return this; }}
构造方法: 如果没有给,系统会默认给一个无参构造
如果给了构造方法,系统不再提供默认的无参构造
注意:这个时候如果想使用无参构造方法,就必须自己给出
建议永远自己给出
构造代码块表示构造函数的共同部分代码块。构造代码块在每个构造函数打印之前都会被打印。
static : 多个对象相同的成员变量用 static修饰,被所有对象共享
例子: person类 属性:姓名,年龄 共同的属性:国籍是中国
静态的变量,可以直接通过类名调用person.country(推荐);
也可以通过创建对象后,用对象名调用p.country
特点总结 : A:随着类的加载而加载
B:优先于对象存在
C:被类的所有对象共享:判断是否使用静态关键字的条件
D:可以通过类名调用
注意:在静态方法中没有this关键字
静态方法只能访问静态的成员变量和静态的成员方法
静态方法:只能访问静态的成员变量和静态成员方法(静态只能访问静态)
非静态方法:可以访问非静态的成员变量也可以访问静态的成员变量
可以访问非静态成员方法和静态成员方法(非静态都可以访问)
静态方法调用非静态的要通过创建对象,利用对象调用。
封装:
A:隐藏实现细节,提供公共的访问方式
B:提高代码复用性
C:提高代码安全性
代码块:使用{ } 括起来的代码被称为代码块,根据其位置不同,分为
局部代码块:局部位置,用于限定变量的生命周期
构造代码块:在类中的成员位置;用{ }括起来的代码,每次调用构造方法执行前,都会先执行构造代码块。作用:可以吧多个构造方法中的共同代码放一起,对对象进行初始化
静态代码块:在类中成员位置,用{ }括起来的代码,只不过它用static修饰
作用:只加载一次,一般是对类进行初始化。
面试题:静态代码块只执行一次,构造代码块每次都执行
继承 (is a):核心是向上转型 (实际开放中最好继承自抽象类,不超过三层)
组合:组合是有一个。房子有一个厨房。
类与类产生了关系,其实也是继承的一个弊端:类的耦合性增强了
开发的原则:低耦合,高内聚
耦合:类与类的关系 内聚:就是自己完成某件事情的能力
继承注意事项:
A:子类只能继承父类所有 非私有的成员(成员变量,成员方法 )(打破封装)
B:子类不能继承父类的构造方法,但是可以通过super访问父类构造方法
C:不要为了部分功能而去继承
A:子类中的成员变量和父类中的成员变量不相同时,直接输出
B:子类中的成员变量和父类中的成员变量不相同时,就近原则:
a:在子类方法的局部范围找,有就用
b:在子类的成员范围找,有就使用
c:在父类的成员范围找,有就用
d:如果还没有,则报错
this代表本类对应的引用
super代表父类存储空间的标识()
super(); this()都必须放在构造函数第一行!
继承中构造方法的关系:
子类中的所有的构造方法默认都会访问父类中空参数的构造方;原因:子类初始化前,一定先完成父类数据的初始化
注意:子类的每一个构造方法第一条语句都是默认:super();
如果父类没有无参构造方法,会报错;如果不写构造函数,系统会默认给父类一个无参构造;
解决:A:在父类加一个无参构造
B:通过使用super关键字去显示的调用父类的带参构造方法
C:通过this调用本类无参构造函数
继承中成员方法的关系:
A:子类中的方法和父类中的方法名不一样,调谁走谁
B:子类中的方法和父类中的方法名一样时候,(方法重写)
a:先找子类中有没有这个方法,有就使用
b:再看父类中有没有这个方法,有就使用,没有就报错!(子类有后执行了,父类就不再执行)
方法重写:子类中出现了和父类中方法一模一样的方法(方法覆盖、复写)
方法重写为了,继承父亲功能(super.方法),再添加新功能
方法重写注意: A:父类中的私有方法不能被重写(父类私有方法子类根本无法继承) B:子类重写方法是,访问权限不能更低。
C:父类静态方法,子类也必须通过静态方法进行重写(根本不叫重写,后面中多态再看)
所以!重写方法时,子类与父类的声明最好一摸一样!这样才不会有问题
方法重载(overload):同类中,出现同名不同参的方法
继承注意: A:成员变量 就近原则
B:this(当前对象引用)和 super(父类的引用)
C:子类构造方法执行前默认先执行父类的无参构造方法
D:一个类的初始化过程:成员变量进行初始化;默认初始化;显示初始化;构造方法初始化
构造方法: A:一个类的执行流程:静态代码块 > 构造代码块 > 构造方法
子类父类都有静态代码块,先父类静态代码块,后子类静态代码块,在构造代码块
B:静态的内容随着类的加载而加载,静态代码的内容会优先执行
C:子类初始化之前,先进行父类的初始化(父类静态代码块)
final :如果不想让子类的方法覆盖掉父类的功能,只能让他使用
特点:final可以修饰类,则该类不能被继承:final class Fu{ }
final可以修饰方法,则该方法无法被重写:public final voidshow(){ }
final可以修饰变量,则该变量不能被重新赋值。这个变量其实是常量:final int x=10;
final 修饰基本类型变量时,值不可改变
final 修饰引用类型变量时,地址值不可改变,但是对象堆内存的值可以变
final修饰变量的初始化时机:
A:被final修饰的变量只能被赋值一次
B:在构造方法完毕前(非静态的产量)
静态继承中执行的顺序:先父静态,后子静态,再父构造,子构造,成员方法;静态只执行一次
创建子类对象时:按顺序执行: 父 static{ }、子static{ }
父构造{ }、父{ }
子构造{ }、子{ }
属性私有化;加访问器、生成器;复写toString;复写hashcode、equals
面向对象核心:对扩展开放,对修改关闭
多态:一个食物,在不同时刻表现出来的不同状态
例子: Catc =new Cat();
Animala= new Animal(); //多态
多态的前提: 提高代码的维护性,扩展性。
A:要有继承关系
B:要有方法重写
C:要有父类引用指向子类对象
Fuf = new Zi();
静态方法: 编译看左边,运行看左边。
构造方法: 创建子类对象时,访问父类构造!对父类数据初始化。
成员方法: 编译看左边,运行看右边(方法重写,所以它特殊,运行看子类)
多态时如何使用子类特有功能呢?
A:创建子类对象,调方法。(不推荐,又创建了对象,浪费资源)
B:把父类的引用强制转换为子类的引用(向下转型)
Zi z=(Zi)f; z.show(都有的方法); z.method(子类特有);
对象间的转型问题:
向上转型:
Fuf =new Zi(); //这个就是多态;创建子类对象,不能实现子类特有功能。孔子装爹。
向下转型:
Ziz =(Zi)f;//要求该f必须是能够转换为Zi。实现子类特有功能
单例设计模式:从程勋运行开始只有一份实例。?????????????
实现:两种,一种是普通类,一种是静态内部类
特征:将构造方法私有化。单例模式提供一个公有方法让其他方法访问实例
测试是不是单例:打开断电:看起Thread的数目,如果有1个Thread就是单线程,是多个就是多线程
A:私有属性(自己创造自己)
Private static Simple instance = new
B:私有化构造方法
C:提供一种对外访问的方式
enum :枚举
public enum EJiJie{
SPRING(“春”),SUMMER(“夏”);
privateEJiJie(StringjieJie){ } //传参必须加构造,私有化!
抽象类
特点:A:抽象类和抽象方法都必须用abstract关键字修饰
Abstract class Animal{ }
B:抽象类中不一定有抽象方法,但是有抽象方法的类必须定义为抽象类
Public abstract void eat();不能加{ } 因为抽象方法不能有主题
C:抽象类不能实例化,因为他不是具体的。
D:抽象的子类
a:如果不想重写抽象方法,该子类是一个抽象类(abstract class)
b:重写所有的抽象方法(不抽象),这个时候子类是一个具体的类。
抽象类 的实例化其实是靠具体的子类实现的,是多态的体现形式
抽象类的成员特点:
成员变量:既可以是变量,也可以是常量
构造方法:有。用于子类访问父类数据的初始化
成员方法:既可以是抽象的,也可以是非抽象的;抽象的集成类要重写
抽象类的方法特性:
A:抽象方法 强制要求子类做的事情
B:非抽象方法 子类继承的事情,提高代码的复用性
接口:
A:接口关键字 interface
interface接口名{ }
B:类实现接口用implements表示
class类名implements 接口名{ }
C:接口不能实例化
那么需要按照多态的方式来实例化
D:接口的子类
a:可以是抽象类,但意义不大
b:可以是具体类。要重写接口中的所有抽象方法。(推荐)
由此可见:
A:具体类多态(几乎没有)
B:抽象类多态(常用 )
C:接口类多态(最常用的)
接口成员特点
成员变量:只能是常量,并且是静态的
默认修饰符:public static final (建议永远自己给,面试才不会错)
构造方法:没有构造方法。使用Object初始化子类构造函数
成员方法: 只能是抽象方法
默认修饰符:public abstract (建议自己手动给)
类与类: 继承关系,只能单继承,可以多层继承
类与接口: 实现关系,可以单实现,可以多实现
并且还可以继承一个类的同时实现多个接口。
例: class Son extends Object implements Father,Mother{ }
例: interface Sister extends Father,Mother{ }
抽象类和接口的区别(面试)
A:成员区别
抽象类:
成员变量:可以变量,可以常量
构造方法:有
成员方法:可以抽象,也可以非抽象
接口:
成员变量:只可以常量
成员方法:只可以抽象
B:关系区别
类与类: 继承关系,只能单继承,可以多层继承
类与接口: 实现关系,可以单实现,可以多实现
接口与接口:继承关系,可以单继承,也可以多继承。
C:设计理念区别
抽象类:被继承体现的是“is a”的关系。抽象类中定义的是该继承体系的共性功能。
接口类:被实现体现的是“like a”的关系。接口中定义的是该继承体系的扩展功能(像usb口)。
实现的时候:从抽象到具体
使用的时候:使用具体类
抽象类没有对应的具体类就用不了,它需要子类来实现
形式参数: 基本类型:简单不讲
引用类型: 类:需要的是该类的对象
抽象类:需要的是该抽象类的子类对象
接口: 需要的是该接口的实现类对象
返回值类型:
基本类型:简单
引用类型: 类: 返回的是该类的对象
抽象类:返回的是该抽象类的子类对象
接口:返回的是该接口的子类对象
链式编程:每次调方法后返回的是一个对象
权限修饰符:private 、默认的、protected、public
状态修饰符:static、final
抽象修饰符:abstract
类: 权限修饰符:默认的、public
状态修饰符:final
抽象修饰符:abstract
成员变量: 权限修饰符:private 、默认的、protected、public
状态修饰符:static、final
构造方法: 权限修饰符:private 、默认的、protected、public
成员方法: 权限修饰符:private 、默认的、protected、public
状态修饰符:static、final
抽象修饰符:abstract
内部类:定义在其他类的内部。
内部类访问特点: A:内部类可以直接访问外部类的成员,包括私有
B:外部类要访问内部类的成员,必须创建对象
内部类位置: 成员位置:在成员位置定义的类,成为成员内部类
局部位置:在局部位置定义的类,被称为局部内部类
静态内部类:不能访问外部类的非静态属性(成员),可以访问外部的成员方法,也可以放外部的静态成员和静态方法
普通内部类:可以访问外部类的私有成员属性,也可以访问外部类的私有方法,行似内部,神似外部,只加载一次(安全)
成员内部类:
A:如何直接访问内部类的成员
B: 在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用内部类功能
外部类名.内部类名对象名 = 外部类对象.内部类对象;
Outer.Inneroi =new Outer().new Inner();
oi.show()
面试题:
this.num; outer.this.num;通过外部类名.this限定外部类
局部内部类:
A:可以直接访问外部类的成员
B:在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用内部类功能
面试题:
局部内部类访问局部变量的注意事项?
局部内部类方位的局部变量必须用final修饰。因为局部变量时随着方法的调用而调用,随着调用完毕而消失,而堆内存的内容并不会立即消失。所以,我们加final修饰。加入final修饰后这个变量就成了常量。既然是常量,消失以后,在内存在存储的是常量数据不会改变,所以还有数据使用。
匿名内部类 :就是内部类的简化写法。(不好理解,记住格式即可,)
(匿名内部类是好莱坞原则:你不要来找我,我来找你。)
安卓常用
前提:存在一个类或者接口。这里的类可以是具体类和抽象类
格式: new 类名或接口吗(){ 重写方法}
本质:是一个继承了该类或实现了该接口的子类匿名对象;是个对象,在后面“.方法();”调用方法
简单写法,多态方式创建对象。(用在类类型,传参)
优点:用完后被回收!次数少用这个,次数多用接口
匿名内部类实例: 匿名内部类在开发中的使用
interface Person {
publicabstract void study();
}
class PersonDemo {
//接口名作为形式参数其实这里需要的不是接口,而是该接口的实现类的对象
publicvoid method(Person p) {
p.study(); }}
//实现类
class Student implements Person {
publicvoid study() {
System.out.println("好好学习,天天向上"); }}
class InnerClassTest2 {
publicstatic void main(String[] args) {
//测试
PersonDemopd = new PersonDemo();
Personp = new Student();
pd.method(p);
System.out.println("--------------------");
//匿名内部类在开发中的使用
//匿名内部类的本质是继承类或者实现了接口的子类匿名对象
pd.method(newPerson(){
publicvoid study() {
System.out.println("好好学习,天天向上");
} });//到这里是匿名内部类,就是对象,作为参数 }}
API常用类:
*String类/StringBuffer类/StringBuilder类
*数组高级和Arrays类
*基本类型包装类(Integer,Character)
*正则表达式(Pattern,Matcher)
*Math类/Random类/System类
*BigInteger类/BigDecimal类
*Date类/DateFormat类/Calendar类
Character、Integer。。其他都是首字母大写
基本类型 byte short int char long float double boolean
包装类型 Byte Short Integer CharacterLong Float Double Boolean
Object类方法:
*public int hashCode();返回该对象的哈希码值。(理解为地址,其实并不是地址值,而是根据地址通过哈希码计算出来的一个值)
*public final Class getClass();返回此Object 的运行时类,就是对象(字节码文件对象) Class类的方法:
public StringgetName():以String形式返回此Class对象所表示的实体对象的全路径名称
*public String toString();返回该对象的字符串表示。
*public Booleanequals(Object obj);指示其他某个对象是否与此对象“相等”。这个方法,默认情况下比较的是地址值,比较地址值一般意义不大,所以要重写这个方法。
一般用equals方法重写比较对象的成员变量的值。
重写的代码优化:提高效率,提高程序的健壮性。其实还是自动生
“==”:基本类型:比的就是值是否相同
引用类型:比较的就是地址值是否相同
equals:引用类型:默认情况下,比较的是地址值。
equalsIgnoreCase():比较值,不分大小写!验证码中常用
*protected void finalize():当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法,用于垃圾回收,但是什么时候回收不确定。(了解)
*protected Object clone():创建并返回此对象的一个副本
A:重写该方法;自动生成
Cloneable:此类实现了Cloneable接口,以指示Object.clone()方法可以合法的对该实例进行按字段复制,这个接口是标记接口,告诉我们实现该接口的类就可以实现对象的复制;克隆后的值改不动
Scanner类:
System类下有一个静态的字段:
public static final InputStream in;标准的输入流键盘录入
InputStreamis =System.in;
构造方法: Scanner(InputStreamsource)
A:创建对象 Scanner input =new Scanner(Sysem.in);
*public Boolean hasNext():判断是否是某种类型的元素
if(sc.hasNextInt()){ }else{ }
*public Xxx nextXxx():获取该元素
Scanner sc =new Scanner(Sysytem.in);
*public int nextInt():获取一个int类型的值
*public String nextLine():获取一个String类型的值
注意:两个数据,先int再String时,输入第一个int时,回车!回车会被赋予给第二个数据:String,就会出现第二个无法输入、两个数据类型都是String时不会出现这个问题。
解决:
A:先获取一个数值后,再创建一个新的键盘录入对象获取字符串
B:把所有的数据都先按照字符串获取,然后要什么,就转换成什么
String字符串: 例:byte[]bys={97,98,99};
构造方法: String s =new String(bys);
publicString(byte[] bytes):把字节数组转成字符串
例:byte[] bys={97,98,99,100}; 97代表a
public String(byte[]bytes,int index,int length):
把字节数组的部分转成字符串,从哪开始,数几个字符。
publicString(char[] value): 把字符数组转成字符串
public String(char[]value,index,int count):
把字符数组的一部分转成字符串
publicString(Stringoriginal):把字符串常量值转成字符串
字符串的方法:
publicint length():返回此字符串的长度。
字符串的特点:一旦被赋值,就不能被改变。
面试题: 比较s1和s2的区别?
String s1 =new String (“hello”);
String s2=“hello”
有,前者会创建2(或1个,一般答两个)对象
后者创建1个(或0个,一般答1个)对象
== :比较引用类型比较的是地址值是否相同
equals:比较引用类型默认也是比较地址值是否相同,而String类重写了equals()方法,比较的内容是否相同。
Syso(s1==s2);//false Syso(s1.equals(s2));//true
String类的判断功能: s1.equals(s3);
boolean equals(Object obj):比较字符串的内容是否相同,区分大小写
boolean equalsIqnoreCase(String str): 比较字符串的内容是否相同,忽略大小写
boolean contains(String str):判断大字符串中是否包含小字符串
boolean endsWith(String str):判断字符串是否以某个指定的字符串结尾
boolean isEmpty():判断字符串是否为空
注意:1:字符串内容为空(对象存在,没有数据)2:字符串对象为空
1:String s =“”; 2:String s =null;
String类的获取功能: s.length(); s.indexOf(“indow”);
int length():获取字符串的长度
char charAt(int Index):获取指定索引位置的字符
int indexOf(int ch):返回指定字符在此字符串再次字符串中第一次出现的索引 。 之所以是int类型,因为‘a’和97都可以代表‘a’
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):从指定位置开始到指定位置结束截取字符串
遍历字符串:
for (int x =0;x<s.length();x++){
Syso(s.charAt(x));}// s.charAt(x)获取对应索引位置的字符
String类的转换功能: 疑问:byte(97)和char(a)区别:‘a’就是97
利用:String ss=String.valueOf(c);
byte[] getBytes():把字符串转换为字节数组。
char[] toCharArray():把字符串转换为字符数组。
static String valueOf(char[]chs):字符数组转成字符串
static StringvalueOf(int i):把int类型数据转成字符串
注意:String类的valueOf方法可以把任意类型的数据转成字符串
String toLowerCase():把字符串转成小写
String toUpperCase():把字符串转成大写
String concat(String str):把字符串拼接
String s=String(ch[],0,0.length)
String类的其他功能:
替换功能:
String replace(char old,char new) //替换一个字符
String replace(String old, Stringnew)//替换一个字符串
去除字符两端的空格: String trim();
Split(): 按照两端有什么,提取所有这样中间的内容
按字典顺序比较两个字符串:s1.compareTp(s2)
int compareTo(String str)//首字符ASCII码相差值(不分大小写);前减后
int compareToIgnoreCase(String str) 首字符ASCII码相差值(不分大小写)
StringBuffer类
线程安全的可变字符串;安全:同步 不安全:不同步。
已经重写了toString方法
StringBuffer和String的区别?
StringBuffer长度和内容可变,而String不可变
如果使用StringBuffer不会浪费太多空间
StringBuffer构造方法:
publicStringBuffer():无参构造
publicStringBuffer(int capacity):指定容量的字符串缓冲区对象
public StringBuffer(Stringstr):指定字符串内容字符串缓冲区对象
StringBuffer方法:
publicint capacity():返回当前容量,理论值
publicint length():返回长度(字符数),实际值
StringBuffer的添加功能:
public StringBuffer append(String str):可以把任意类型添加到字符串缓冲区里,并返回字符串缓冲区本身。此为非静态方法需创建对象后使用,可多次调用。
public StringBuffer append(intoffset,String str):在指定位置把任意类型的数据插入到字符串缓冲区里面,并返回字符串本身
StringBuffer的删除功能
public StringBuffer deleteChatAt(intindex):删除指定位置的字符,并返回本身
public StringBuffer deleteChatAt(intindex,intend):删除指定位置开始,指定位置结束的字符,并返回本身
StringBuffer的替换功能: s.replace(2,4,“啊哈哈”);
Public StringBuffer replace(intstart,int end,String str):从start开始到end结束用str替换
StringBuffer的反转功能: s.reverse();
public StringBufferreverse();
StringBuffer的截取功能:截取int值以后长度的字符串,并返回String类型,而本身StringBuffer并没有发生改变
public String substring(intstart);
public String substring(intstart,int end);包左不包右
A转换为B:其实是为了使用B的功能
B转换为A:我们要的是A的类型,所以还要转回来
String和StringBuffer的互相转换:
String--->StringBuffer
A:通过构造方法
StringBuffer sb =new StringBuffer(s)
B:通过append的方法
StringBuffer sb2 =new StringBuffer(); sb2.append(s);
StringBuffer---> String
A:通过构造方法 Stringstr =new String(sb)
B:toString()方法 str.toString()
StringBuilder 一个可变的字符序列。SufferBuilder的简易替换。线程不安全,字符串缓冲区被单线程使用时使用!
面试题: 1、String,StringBuffer,StringBuilder的却别?
A:String是内容不可变的,而StringBuffer,StringBuilder是内容可变的。
B:StringBuffer是同步的,数据安全,效率低;StringBuilder是不同步的,数据不安全,效率高
2、StringBuffer和数组的区别?
二者都可以看成一个容器,装其他的数据,但是StringBuffer的数据最终是一个字符串数据。而数组可以是放置多种数据,但必须是同一种数据类型的。
3、形式参数问题:
String作为参数传递
StringBuffer作为参数传递
基本数据类型:形式参数的改变不会影响实际参数
引用数据类型:形式参数的改变直接影响实际参数
注意:String作为参数传递,效果和基本类型作为参数传递是一样的
StringBuffer作为参数传递:最好不要作为形式参数传递!建议调方法!
Sting类和正则表达式相关的类 汉字:ch[x]<'\u9fa5' && ch[x]>'\u4e00'
正则表达;\d 数字:[0-9] \w等价于[a-zA-Z_0-9] ?:[0-1]次 +:[1,n次
. :代表任意字符 *:1-n次
String str ="9237492wer3874";
//qq号以1-9开头,后面有4-14位数字
String regex="[1-9]\\d{4,14}"; //\d 数字:[0-9]
boolean boo = str.matches(regex);//验证qq号是否和正则表达式匹配
System.out.println(str+":"+boo);
String ss = "door";
String regex2 ="do?r";//?前面的字符出现0-1次
boolean bo = ss.matches(regex2);
System.out.println(ss+":"+bo);//false
String regex3 = "do.r";//.表示一个任意字符
boolean bo3 = ss.matches(regex3);
System.out.println(ss+":"+bo3);//true
String中的类: matches(正则表达规则) 是否符合规则
Pattern p =Pattern.compile("\\w+@\\w+(\\.\\w+)+");
Matcher matcher2 =p.matcher(content);//String content=”sssssss”
声明的形参类型是CharSequence接口类型,实际传入的是String实现类对象
while(matcher2.find()){
System.out.println(matcher2.group());}
正则表达式的应用
* 判断功能 public boolean matches(String regex)
* 分隔功能 public String[] split (String regex)
* 替换功能
public String replaceAll((String regex,String replacement)
*获取功能 Pattern和Matcher matches
Random:
* public Random():没有给种子,用的是默认种子,是当前时间的毫秒值
* public Random(Long seed):给出指定的种子;给后,每次得到的随机数都是相同的
方法:
Public int nextInt():返回的是int范围内的随机数
Public int nextInt(int n):返回的是[0,n)范围内的随机数
System类包含一些有用的类字段和方法,它不能被实例化。
方法:
*public static void gc(): 建议运行垃圾回收器,
调用System.gc();实际相当于Runtime.getRuntime().gc();
*public static void exit():
*public static longcurrentTimeMillis()
*public static voidarraycopy(Object src,int srcPos,Object destPos,int length)
*double sin (double a) 计算角 a的正弦值;传的是对应角度的弧值
例子:Math.sin(2*Math.PI/360*30) 30度的正弦值
*double ceil (double a): 向上取整
*double floor (double a): 向下取整
*double round(double a): 四舍五入
Math类:
静态常量--PI :圆周率的double值
double pow (double a, double b) 计算 a 的 b 次方
double random() 返回带正号的double值,该值大于等于0.0且小于1.0
DATE类:
Date date=new Date();当前的时间日期
java.util.Date: 包装了一个long类型的数据,表示与GMT标准时间1970年1月1日 00:00:00 这一刻相差的毫秒数
java.text.SimpleDateFormat:对日期进行格式化
SimpleDateFormatsdf=new SimpleDateFormat(“yyyy--MM--dd EEE hh-mm-ss”);//EEE是星期
Stringtime=sdf.format(date);//格式化时间
日期-->文本(format()) 文本-->日期(parse())
日历Calendar类:
获取Calendar类的实例的方法
*A:使用 Calendar.getInstance();
*B:返回它的子类GregorianCalendar的对象
一个Calendar的实例是系统时间的抽象表示,可以通过这个实例上的get(int field)方法来取得想要的时间信息。例如:Calendar.YEAR
public intget(int field) 根据给定的日历字段获得当前时间中相应字段的值。
System.out.println("年: " + objCalendar.get(Calendar.YEAR));
// 一年中的第一个月是JANUARY,它为0
System.out.println("月: " + (objCalendar.get(Calendar.MONTH)));
System.out.println("日: " + objCalendar.get(Calendar.DATE));
System.out.println("星期: " +(objCalendar.get(Calendar.DAY_OF_WEEK)));
System.out.println("小时: " + objCalendar.get(Calendar.HOUR_OF_DAY));
System.out.println("分钟: " + objCalendar.get(Calendar.MINUTE));
System.out.println("秒: " + objCalendar.get(Calendar.SECOND));
BigDecimal类 :运算float、double类型运算
高级数组与排序:
冒泡排序:相邻两两比较,最大值就出现在了最大索引。同理继续:排序了
2、第一次比较完毕后,下一次比较的时候就会减少一个元素的比较
3、总共需要比较数组长度-1次。(最后一次不用比)
publicstaticvoidbubbleSort(int[] arr){
for(intx=0;x<arr.length-1;x++){
for(inty=0;y<arr.length-x-1;y++){
if(arr[y]>arr[y+1]){
inttemp=arr[y];
arr[y]=arr[y+1];
arr[y+1]=temp;
}
}
}}
重点在每一个y都在和一排的数在比。最大的放后面
原理:0索引开始,一次和后面比较,小的往前放,第一次完毕,最小值就出现最前面,同理可得排序好
规律:1、第一次是从0索引开始和其他的进行比较,第二次是从索引1开始比
2、最后一次是数组长度-2的元素和数组长度-1的元素比较
publicstaticvoidselectSort(int[] arr){
for(intx=0;x<arr.length-1;x++){
for(inty=x+1;y<arr.length;y++){
if(arr[x]>arr[y]){
inttemp=arr[x];
arr[x]=arr[y];
arr[y]=temp;
}} }}
重点在:每一y在和x比。
数组查找:
基本查找:数组元素无序(从头找到尾,找不到就返回-1)
无序必须用基本查找!!!!!!!
二分查找(折半查找):数组元素有序
publicstaticintgetIndex(int[]arr,intvalue){
intmax =arr.length-1;
intmin =0;
intmid = (max+min)/2;
while(arr[mid]!=value){
if(arr[mid]>value){
max = mid - 1;
}elseif(arr[mid]<value){
min=mid+1;
}
if(min>max){
return -1;
}else{
mid = (max +min)/2;
}}
returnmid; }}
Arrays类:
此类包含针对数组排序查找的功能。
1、public static String toString (int[]a):把数组转成字符串
2、public static void sort(int[] a):对数组进行排序(对任意数组操作)
3、public static int binarySearch(int[]a,int key)二分查找
4、进制转换:二进制toBinaryString();八进制toOctalString();
十六进制:toHexString();
将基本数据类型对象的封装成包装类。基本类型对应首字母大写,就可以使用方法;常用的操作之一: 用于基本类型和字符串之间转换
包装类类型:Byte、Short、Integer、Long、Float、Double 、Character、Boolean(所有类的使用大致一样)
Integer类:
构造方法:
publicInteger(intvalue): Integeriii=new Integer(s);
publicInteger(String s) s这个字符串必须是有数字组成的
成员方法:字符串和int类型之间的转换(其他类型类似,)
int-->String: String.valueOf(number):类似Integer.valueOf()
String—>int: Inter.parseInt(s) :类似 Float.parseFloat
集合框架
集合体系
|--Collection
|--List:元素是有序的,元素允许重复,因为该集合体系都具有索引
|--ArrayList:底层数据结构是数组,查询速度快,增删操作较慢,线程不同步
|--LinkedList:底层数据结构是链表,查询效率较低,增删操作快,线程不同步
|--Vector:功能同ArrayList类似,底层也是数组,不同是线程是同步的,效率较低
|--Set:元素是无序的,元素不允许重复
|--HashSet:底层hash表,存储的对象最好复写hashCode和equals方法,保证元素不会重复
|--LinkedHashSet:有序,hashset的子类。
|--TreeSet:底层二叉树,存储的对象具备比较性,有两种方法,对Set集合中的元素的进行指定顺序的排序。
|--Map:数据是以键值对的形式存储的,有的元素存在映射关系就可以使用该集合,元素不允许重复
|--HashMap:可以存储null键或值,线程不同步。替代了Hashtable.
|--TreeMap:底层是二叉树结构,可以对map集合中的键进行指定顺序的排序。Key只有一个为null;值可以有任意个 null。
|--HashTable:类似HashMap,不可以存储null键或值,线程同步
面试题:Map底层的‘键’是用Set来存储的!
Collection接口中定义的方法:
List
*int size();元素数
*get(int index)、add(int index,Objectelement)、
*set(int index,Object element)、remove(int index)
*subList(int formIndex,int s)
汉字比较器:
CollationKeykey1=Collator.getInstance().getCollationKey(a);
CollationKeykey1=Collator.getInstance().getCollationKey(b);
按特定规律比较的类。Key1.compareTo(key2)
比如城市的排序。。。。。
HashSet遍历: 没有get方法,不能用普通for
- A:增强for
- B:Iterator迭代器
TreeSet集合排序有两种方式,Comparable和Comparator区别:
1:让元素自身具备比较性,需要元素对象实现Comparable接口,覆盖compareTo方法。
2:让集合自身具备比较性,需要定义一个实现了Comparator接口的比较器,并覆盖compare方法,并将该类对象作为实际参数传递给TreeSet集合的构造函数。
第二种方式较为灵活。
Map集合存储和Collection有着很大不同:
Collection一次存一个元素;Map一次存一对元素。
Collection是单列集合;Map是双列集合。
Map中的存储的一对元素:一个是键,一个是值,键与值之间有对应(映射)关系。
特点:要保证map集合中键的唯一性。
Collection 和 Collections的区别:
Collections是个java.util下的类,是针对集合类的一个工具类,提供一系列静态方法,实现对集合的查找、排序、替换、线程安全化(将非同步的集合转换成同步的)等操作。
Collection是个java.util下的接口,它是各种集合结构的父接口,继承于它的接口主要有Set和List,提供了关于集合的一些操作,如插入、删除、判断一个元素是否其成员、遍历等。
(s)JDK5的新特性
自动装箱:把基本类类型转换为包装类类型
自动拆箱:把包装类类型转换为基本类型
注意一个小问题:在使用时,Integerx=null;会出现NullPointerException空指针异常
Character类:
Character类在对象中包装了一个基本类型chard 的值,该类提供了几种方法;以确定字符的类别(小写字母,数字,等等),并将字符从大写转成小写。
构造方法: Characterch=new Character(‘a’);//97
Character(char value)
成员方法: publicstatic Boolean isUpperCase(char ch);判断是否是大写
public static BooleanislowerCase(char ch);判断是否是小写
public static BooleanisDigit(char ch);判断是否是数字字符
public static char toUpperCase(charch);把给定的字符转换为大写字符
public static char toLowerCase(charch);把给定的字符转换为小写字符
IO流:
字节流InputStream/OutputStream
|--FileInputStream/FileOutputStream:文件字节流,用于文件的读写操作
|--BufferedInputStream/BufferedOutputStream:加缓冲区的字节流,用于提高效率
字符流Reader/Writer
|--FileReader/FileWriter:文件字符流,用于文本文件的读写操作
|--BufferedReader/BufferedWrite:加缓冲区字符流,用于提高效率
转换流InputStreamReader/OutputStreamWriter:是字节流和字符流之间的桥梁
配置文件Properties
异常的概念:运行时发生的不正常的时间,中断程序的正常运行!
异常处理机制:
异常的分类:error:错误,需要jvm来承担错误,程序员无法修正错误!
Exception:异常
检查异常:编译器提示必须要处理的异常
非受检(运行时)异常:编译器不要求必须处理的异常
InputMismatchException:输入类型不匹配
ArithmeticException:算术异常(除数不能为0)
非受检异常:编译器不要求必须处理的异常
ClassCastException:错误的类型转换
ArrayIndexOutOFException:数组下标越界
NullPointerException:空指针异常
ArithmeticException: 算术异常(除数不能为0)
受检异常:编译器要求必须处理的异常 (由外部元素造成的)
ClassNotFoundException:没有找到指定名称的类
FileNotFoundException:访问不存在的文件
IOException:操作文件时发生的异常
SQLException:操作数据库时发生的异常
方式A:try...catch...finally 变形格式:
try{ try{
可能出现问题的代码 可能出现问题的代码
}catch(异常名 变量){ }catch(异常名变量){
针对问题的处理 针对问题的处理;
}finally{ }
释放资源; }
注意:1、try里面代码越少越好!占用资源!
2、catch里面必须有内容,哪怕是一个简单的提示
方式B:
throws 异常名
注意:
这个格式必须跟在方法的括号后面;跟的是异常类名,可多个。不一定异常
throw用在方法内!跟的是异常对象名,只能抛出一个异常对象名。一定异常
最好用try... catch
finally:被finally控制的语句体一定会执行。
特殊情况:System.exit(0);JVM退出了
finally的作用,用于释放资源,在IO和数据库用到
final,finally,finalize的区别
Final:修饰类,不能被继承,修饰变量,变量时常量,修饰方法,不能重写
Finally:是异常处理的一部分,用于释放资源,一般来说,代码肯定会执行; 除非JVM退出
Finalize:它是一个Object方法:当某个对象为空或被引用较少,在回收对象时,自动调用它,不可以被手动调用;系统的垃圾回收机制,用于回收垃圾。
File类:
File文件和目录(文件夹)路径名的抽象表示形式
*Filefile1=new File(“E:\\demo\\a.txt”);//指向一个路径
Filefile2=new File(“E:\\demo”,“a.txt”);//指向一个路径
Filefile3=new File(“E:\\demo”);//指向一个路径
Filefile4=new File(“a.txt”);//以上,1,2,3和4的效果一样
创建功能: 创建文件没有指定文件夹路径时,默认在当前工作空间里面
Publicboolean createNewFile():创建文件,如果存在就不创建了
File file1=new File(“E:\\demo\\a.txt”);
File.createNewFile();//创建了一个a.tst
Publicboolean mkdir():创建文件夹(true),如果存在,就不创建了(flase) Filefile1=new File(“E:\\demo”)
File.mkdir();//创建了一个demo文件夹
*Publicboolean mkdirs()::创建文件夹,在文件夹里创建内容(前面一个目录没有时,创建目录里文件的方法)
删除功能: java中的删除不走回收站!
Publicboolean delete(); //文件文件夹都可以删除
File file=new File(“E:\\demo”);
File.delete();
判断是否是文件夹:isDirectory();
判断是否是文件:isFile();
获取绝度路径:getAbsolutePath();
文件过滤器:自定义一个过滤器
//找出制定文件夹中后缀名为:“txt”和“docx”的和“doc”的所有文件
classimageFileter implementsFilenameFilter {
publicbooleanaccept(File file, String name){
if(name.toLowerCase().endsWith(".txt")||name.toLowerCase().endsWith(".docx")||name.toLowerCase().endsWith(".doc")){
returntrue;}
returnfalse;}
publicclassTest02 {
publicvoidmain(String[] args) {
Filefile=newFile("D:\\andriod1530");
String[]s=file.list(newimageFileter());
for(String string: s) {
System.out.println(string);
}}}}
IO字节流:
字节流:FileInputStream:输入流;读数据
字节流:FileOutputStream:输出流;写数据
追加输出流FileOutputStream(“a.txt”,true);
缓冲字节流:BufferedInputStream(new FileInputStream()):读
缓冲字节流:BufferedOutputStream(new FileOutputStream()):写
字符流: FileReader :读
FileWriter :写
高效缓冲字符流:BuferedReader(new FileReader):读
高效缓冲字符流:BuferedReader(new FileReader):写
内存流
ByteArrayInputStream和ByteArrayOutputStream
* 不同的操作系统对换行的符号识别是不一样的:
高级记事本:可以识别任意的一个
windows:\r\n ;linux:\n ; mac:\r
Fw.write(bys,0,len);写数据
Fe.newLine();系统自动识别换行
Fe.flush();刷新缓冲区里面的数据到输出流
装饰者模式:在已知的类中,作为一个参数传入,从而达到功能的增强的效果
多线程
*获取正在执行线程的对象的名称:Thread.currentThread().getName();
*获取线程的优先级:getPriority():注意:线程默认优先级5;
*设置线程的优先级:setPriority(int n);范围在(1-10);
*线程休眠:public static void sleep(long mills):当前毫秒内暂停执行
*加入线程;public final void join();等待线程终止(当前线程先执行完
*publicstatic void yield():暂停当前正在执行的线程,并执行其他线程
让多个线程执行更和谐,一对一下的执行,但不是完全绝对的礼让
*后台线程:public static void setDaemon(boolean on):将该线程标记为守护线程或用户线程,当正在运行的线程都是守护线程时,java虚拟机退出,该方法必须在启动线程前调用。
*中断线程:public static void stop();让线程停止,过时了,但还可以使用
public staticvoid interrupt();中断线程,把线程的状态终止,并抛出一个异常(推荐使用)
创建线程的两个方法:
A:创建一个类继承自Thread类,并重写run方法
B:实现Runnable接口,重写run方法:
B方式的好处:1、可以避免由于java单继承带来的局限性
2、适合多个相同程序的代码去处理同一个资源的情况,把线程同程序的代码,数据有效分离,较好的体现了面向对象的设计思想。
Synchronized
锁Lock是个接口:获取锁:lock 是个接口 释放锁unlock
等待唤醒机制:
- 等待:wait(long timeout);超过这个时间就醒过来。
一般用wait(),直接唤醒
- 唤醒单个线程:notify();
- 唤醒对象上所有线程: notifyAll();
*线程组:ThreadGroup;
- 把多个线程组合到一起,它可以对一批线程进行分类管理,java允许程序直接对线程组进行控制。
*线程池:A:
publicstatic ExecutorService newFixedThreadPool(int nThreads)
B:这种线程池的线程的线程可以执行:执行Runnable对象或Callable 对象代表的线程;做一个类实现Runnable接口
C:调用如下方法即可:
Future<?>submit(Runnable task)
<T>Future <T> submit(Callable<T> task)
===================================================
创建线程池对象(对应A:)
ExecutorServicepool=Executors.newFixedThreadPool(2);
执行Runnable对象或者Callable对象代表的线程:(对应B)
写一个MyRunnable类实现 Runnable接口,重写run方法
Pool.submit(newMyRunnable());
Pool.submit(newMyRunnable());
结束线程池
Pool.shutdown();
定时器
*Timer:
反射:
就是通过class文件对象,去使用该文件中的成员变量,构造方法,成员方法。
构造方法的反射使用:
/* 通过反射获取构造方法并使用。
* A:获取字节码文件对象
* B:获取构造方法(构造器)
* C:实例化;带参数加对应类型参数 */
public static void main(String[] args)throws Exception {
//A:获取字节码文件对象
Classc=Class.forName("day926Reflect.Person");
//B:获取单个构造方法constructor;多个加s;私有加Declared,
//有参数,加类似String.class
Constructorcon=c.getConstructor(String.class);
//实例化;带参数加对应类型参数
// 暴力访问实例化后加con.setAccessible(true);
// 值为true则指示反射的对象在使用时应该取消Java语言访问
Objectobj=con.newInstance(“孙震”);
System.out.println(obj); }
成员变量的反射使用:
*通过反射获取成员变量并使用
* 单个私有成员
* A:获取字节码文件对象
* B:获取无参构造器对象;如果加参数(String.class)
* C:实例化:通过构造器创建对象 ;有参加参
* D:获取name并对其赋值,私有类型。Declared建议所有的都加暴力反射
public static void main(String[] args)throws Exception {
//A:获取字节码文件对象
Classc =Class.forName("day926Reflect.Person");
//B:获取无参构造器对象;如果加参数(String.class)
Constructorcon =c.getConstructor();
//C:实例化:通过构造器创建对象 ;有参加参
Objectobj=con.newInstance();
//获取name并对其赋值,私有类型。Declared建议所有的都加暴力反射
FieldnameField=c.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(obj,"孙震");
System.out.println(obj); }
成员方法的反射使用:
* 通过反射获取成员方法:
* A:获取字节码文件对象
* B:获取构造器 getConstructors():所有公共构造方法
* C:实例化 getDeclaredConstructors():所有构造方法
* D:写方法 */
public static void main(String[] args)throws Exception {
//获取字节码文件对象
Classc=Class.forName("day926Reflect.Person");
//获取构造器
Constructorcon=c.getConstructor();
//实例化;带参数加对应类型参数
Objectobj=con.newInstance();
//获取单个方法并使用
//public void show()
//publicMethod getMethod(String name,Class<?>...parameterTypes)
// 第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型
Methodm1=c.getMethod("show");
// 返回值是Object接收,第一个参数表示对象是谁,第二参数表示调用该方法的实际参数 // 调用obj对象的m1方法
m1.invoke(obj);
System.out.println("---------------");
Methodm2=c.getMethod("method",String.class);
m2.invoke(obj,"ahaha");
System.out.println("---------------");
//getString是带返回值的方法
Methodm3=c.getMethod("getString",String.class,int.class);
ObjectobjString=(String)m3.invoke(obj, "YY",22);
System.out.println(objString);
Strings = (String)m3.invoke(obj, "YY",23);
System.out.println(s);
System.out.println("----------");
//私有成员方法
Methodm4=c.getDeclaredMethod("function");
m4.setAccessible(true);
m4.invoke(obj);
}
反射的应用:
通过配置文件运行类中的方法。
反射:需要有配置文件配合使用(用class.txt代替)
键值对数据:properties prop=new properties();
例子:
package cn.itcast.test;
importjava.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
/*
* 我给你ArrayList<Integer>的一个对象,我想在这个集合中添加一个字符串数据,如何实现呢?
*/
public class ArrayListDemo {
publicstatic void main(String[] args) throws NoSuchMethodException,
SecurityException,IllegalAccessException,
IllegalArgumentException,InvocationTargetException {
//创建集合对象
ArrayList<Integer>array = new ArrayList<Integer>();
//array.add("hello");
//array.add(10);
Classc = array.getClass(); // 集合ArrayList的class文件对象
Methodm = c.getMethod("add", Object.class);
m.invoke(array,"hello"); // 调用array的add方法,传入的值是hello
m.invoke(array,"world");
m.invoke(array,"java");
System.out.println(array);
}
}
动态代理:java.lang.reflect下的Proxy类和InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象。只能对接口作代理。
后面框架有更强大的代理cglib
面向对象思想设计原则:
设计模式:
简单工厂模式和工厂方法模式(接口)
模板设计模式(抽象类)
装饰设计模式(IO流)
单例设计模式(多线程)
适配器模式(GUI)
JAVA基础增强:
程序测试调试:JUnit
方法前加@Test
@Before Bofore每个方法测试之前都要执行(常用)
@ BeforeClass 类加载时初始化
@After Bofore每个方法测试之后都要执行(常用)
@ AfterClass 类加载完毕时释放资源
断言:
Assert.assertEquals(“期望返回值”,p.run());
此方法适用很多的类型
通过,则p.run()值与期望值相等 否则不相等
JDK5.0新特性:
静态导入 :导入静态的包后,调用方法不需要写对象名(不推荐使用)
自动装箱/拆箱:基本数据类型—>包装类;包装类—>基本数据类型
例子:List list= newArrayList();
List.add(1);
Intj=(Integer)list.get(0);//装箱
增强for循环:只能用在数组、或实现Iterable的集合接口的集合类上
for(变量类型 变量:需迭代的数组或集合){ }
注意:增强for只适合取数据;
可变参数:可变参数就把他看成数组 sum{1,2,3,4,5}
注意:是引用数据类型,可变参数只能作为方法的最后一个参数
优点:使用前可以不知道具体的可数
可变参数 方法名(数据类型...变量名(数组)){ }
Public static intsum(int...num){ }
int sum=0;
for(int i=0;i<num.length;i++){
sum+=num[i];
}return sum;
求变量名的和。
枚举:限定形式参数;enum相当于申明类的对象
如何定义枚举的构造函数,方法,字段去封装更多的信息
枚举类也是一种特殊形式的JAVA类;枚举类总声明的每一个枚举值代表枚举类的一个实例对象、声明枚举类是,可以声明属性,方法,和构造函数。但枚举类的构造函输必须是私有的!(不私有的话,会被创建对象,就不是枚举了)
枚举类也可以实现借口、或是继承抽象类;
当枚举类只有一个枚举值,则可以当做单态设计模式使用。
简单用法:
name();返回枚举常量的名称
Ordinal()返回此枚举常量的序数(初始序数为0)
字符串转成枚举:枚举类.valueOf(str);
枚举类.values();返回枚举所有值的数组,用于遍历枚举所有枚举值
反射:做框架用(重点)
内省(Introspector):经常封装,每次访问都用反射太麻烦,出现了内省
内省就是操作JavaBean属性:
JavaBean就是封装的一个类就是javabean;javabean的属性不是由成员变量决定的,而是由get或set决定。
//得到beand 所有属性(Person类)
Beanfo info=Introspector.getBeanfo(Person.class,Object.class);
//得到bean自己的属性;Object.class表示继承自Object的属性不要。
PropertyDescriptor[]pds=info.get PropertyDescriptor();
for(PropertyDescriptorpd:pds){syso(pd.getName());}
//操作bean的指定属性:Person类的age属性
Person p=new Person();
PropertyDescriptor pd=newPropertyDescriptor(“age”,person.class);
Method method =pd.getWriteMethod();
method.invoke(p,45);
syso(p.getAge());
Introspector.getReadMethod();获得应该用于读取属性值的方法
Introspector. getWriteMethod();获得应该用于读写入属性值的方法
泛型:限制集合的处理类型,把程序运行时可能发生的问题转变为编译时的问题
以此提高程序的可读性和稳定性(尤其在大型程序中更为突出)
使用泛型是,类型必须为引用类型,不能是基本数据类型。
注意:泛型是提供给javac编译器使用的,它是用于限定集合的输入类型,在源代码基础上挡住非法数据,但编译器编译完成带有泛型的java程序后,生成的class文件中将不再带有泛型信息;一般程勋运行不收影响。这叫“擦除”。
自定义带泛型的方法:
public <T,E,K> void print(T t,E e,K k){ }这是在本方法声明
还可以在类名后声明T。这样除静态方法外,就都可以使用
元数据
面向对象思想设计原则:
*单一职责原则:“高内聚,低耦合”
*开闭原则:对扩展开放(增加代码);对修改关闭(不能修改代码)
*里氏替换原则:在父类出现的地方都可以用它的子类来代替
*依赖注入原则:要依赖于抽象,不要依赖于具体实现
*接口分离原则:不应该强迫程序依赖他们不需要使用的方法
*迪米特原则:一个对象应当对其他对象尽可能少的了解。。
设计模式概述:
*设计模式是一套反复使用,多数人知晓,经过分类编码的,代码设计经验的总结;设计模式不是一种方法和技术,而是一种思想!学习设计模式就是要建立面向对象的思想,尽可能的面向接口编程,低耦合,高内聚,是设计的程序可以复用;
设计模式必须的要素: *名字:有意义的名字
*问题:描述在何时使用模式
*解决防范:妙护设计的组成部分如何解决问题
*效果:描述设计模式的效果以及优缺点
设计模式的分类:
*创建型模式: 对象的创建(简单工厂模式,工厂方法模式,抽象工厂模式,建造者模式,原型模式,单例模式。6个)
*结构型模式:对象的组成/构成(外观模式,适配器模式,代理模式,装饰模式,桥接模式,组合模式,享元模式。7个)
*行为型模式:对象的行为(模板方法模式,观察者模式,状态模式,职责链模式,命令模式,访问者模式,策略模式,备忘录模式,迭代器模式,解释器模式。10个)
简单工厂模式:提供类静态的创建类的方法;返回的是new 对象。私有化构造!优点是:明确了各个类的职责,缺点:添加类要修改代码,不利于维护。
工厂方法模式:抽象工厂类负责对象的创建。优点:增加类只需增加一个工厂类即可。缺点:需要额外的编写代码,增加了工作量。
查漏补缺
一个数亦或(∧)一个数两次,值不变(可以用来加密)
>> 右移,高位是什么就补什么
>>>无符号位移;高位无论是什么都补0
else总是和离它最近的且没有对应else的if对应
switch(){ //()表达式的值需要的是byte、short、char、枚举(jdk1.5)、String(jdk1.7)
case 取值1:
执行语句;
break;
case 取值2:
执行语句;
break;
default:
执行语句;
break;
当循环中用到的变量在循环结束后不再被使用,
*break:结束其所在的循环 continue:结束某一次循环
*return:会返回这个值,并结束该函数调用;回到函数调用的位置
*m:for(int i=1;i<5;i++){
if(i==3){continue} countinue 表示结束i=3的循环
} m是个标记,相当于起名。
使用 break m;结束for循环
一个函数没有返回值也可以使用return;作用是:返回到调用该函数的位置
à提前结束函数调用。
一个函数有返回值,那么在任何情况下都有返回值;(所有情况都要有返回值)
JVM在执行程序时,吧内存分为5块:栈,堆,方法区,本地方法区,寄存器
栈:局部变量;函数语句中定义的变量就是局部变量
特点:局部变量的作用域一旦结束,就会立刻释放内存。(先进后出)
堆:存储的是实体(数组,对象),都是可以存储多个数据的
特点:A:在堆中有默认值
B:有内存首地址
C:有垃圾回收机制,没有引用指向的数组或对象就成了垃圾,等待垃圾回收线程的回收。
堆有默认值,栈没有默认值;
排序算法
选择排序:一次固定每个下标,让每个下标中的值,和后面所有的值分别比较;每次比较出最小的值,放在第一,第二。。。第n个位置。
冒泡排序:下标相邻的两个数进行比较;两两比较;
查找:二分查找;两种思路: A:while(min<=max)
B:while(key!=arr[i])
反转:int[] arr
publicstaticvoid fanZhuan(int[] arr){
for (inti = 0,j=arr.length-1; i<j; i++,j--) {
inttemp=arr[i];
arr[i]=arr[j];
arr[j]=temp; }}
局部变量和成员变量的对比:
1:局部变量没有默认值
成员变量有默认值
2: 局部变量的作用的范围是从其定义的位置开始到其所在的大括号结束
成员变量的作用范围是整个类
3: 局部变量是随着其所在的函数被调用而在栈中开辟内存
成员变量是当创建对象时在堆中开辟内存
4: 局部变量是当期作用域结束时就立刻释放在栈中的内存
成员变量是当其所属的对象被垃圾回收时才释放内存
*生成帮助文档 javadoc –d doc 文件名
*this:是一个引用,总是指向当前正被使用的对象
*构造函数之间的调用使用this,而且必须写在第一行;this();*this(String name,int age);
*static:可以修饰成员(成员变量,成员方法,成员接口等等。。。)特点:
1、static修饰的成员变量的值是该类的所有对象共享
2、static修饰的成员变量是随着类的加载就在方法区的静态区开辟内存了,优先于非静态成员变量的存在;
3、静态成员是随着类的加载就在静态区开辟内存了,所以static修饰的成员变量可以通过类名访问,也可以通过对象访问;而非静态的成员变量是在创建对象时才开辟内存的,所以只能通过对象访问;
缺点:占据内存时间太长
静态方法也叫类方法:
*静态方法只能使用静态成员!
*非静态方法即可以使用静态成员,也可以使用非静态成员
什么时候用static? 静态只能用静态,非静态都可以用!
1. 什么时候把成员变量修饰位static?
当成员变量的值需要被其所属的类的所有对象共享时
2. 什么时候把成员函数修饰位static?
当成员函数没有用到其所属类的任何非静态成员时;
*静态代码块:随着类的加载而执行,且只执行一次。优先于main方法!
-可用于类的初始化,写在静态代码块内
*构造代码块:每次对象一创建就执行,且优先于构造函数的执行。
-可用于同一个类的共性的属性的初始化!
-构造函数只能用于每个对象特有属性的初始化
单例设计模式:23种设计模式,解决某一类问题最有效的方式
单例设计模式:解决一个类在内存中只能有一个对象
1、私有构造 privateSingle(){}
2、创建对象私有并静态private static Single s =newSingle();
3、创建获取对象方法并静态 publicstatic Single gets(){
一般用饿汉式单例设计模式 return s; }
继承:1、实现了代码的重复使用
2、使类和类之间产生了关系,之类,父类
Java中只能单继承;
为什么呢?:如果多个父类有相同的方法时,子类调用时出现调用不确定性!
Java允许多层继承;这样就形成了一个特继承体系,
了解一个体系:看顶层。顶层定义的是整个体系最共性的功能;
使用一个体系:看底层。底层除了有上层的功能,还有自己特有的方法,是功能最全的
不能为了继承而继承,当事物之间存在所属关系时继承(is a)
*this是当前对象的引用
*super不是引用,代表的是父类的数据空间,当子父类中出现同名成员时,
用super来区分;
*父类的私有成员子类无权访问,所以提供public的set,get方法,就能访问
*子类中,成员变量、成员函数都可以用super来区分;
重写:1、子类在重写是,重写的方法的权限必须等于或大于父类的方法的权限
2、静态只能覆盖静态
3、重写的时候方法名,参数必须一致,如果父类中的方法有返回值,那么自雷在重写时,返回值可以和父类一样,也可以是父类返回值的子类类型
4、私有的方法不能被子类重写
*构造函数的特点:在创建子类对象时,总是先执行父类的构造方法,再执行子类的构造方法,原因是系统自动在子类的构造方法的第一行加入了一条语句super();这条语句默认是调用父类中无参的构造方法
为什么先调用父类的构造方法?
因为子类继承了父类,肯定会继承父类的成员变量,在子类构造方法中先调用父类的构造方法可以利用父类中的为成员变量初始化的语句。
-super语句必须写在第一行。 系统自己加的是调用无参的构造,这时候如果父类中没有无参的构造方法,那么必须在子类中手动加入super语句来调用父类中某一个构造方法,所以建议,父类的无参构造写上最好。
*final:
用作符号常亮;public static final int HAPPY=1; 一般大写。类名.HAPPY
*abstract不能和哪些关键字同时使用
1:final:abstract修饰的方法必须可以被重写,final修饰的的方法不能被重写
2:static。抽象的方法不可以被调用,静态的方法可以直接被调用
3:private:abstract修饰的方法必须可以被重写,private修饰的方法私有,子类无权访问
*interface:
-成员变量必须是静态的常量;public static final in NUM=8;
常亮规范上是大写!
-接口可以多实现:解决了java的单继承问题;不会出现调用的不确定性,因为接口中的方法都是抽象的都没有实现,子类在实现多个接口并重写了接口中的方法,在创建子类对象并调用重写的方法时,很明确实是在调用重写的方法
-接口作用:1、一些对外暴露规则,可以提高程序的扩展性;
2、可以降低耦合性(对象和对象之间的依赖关系)
接口和抽象类分别在什么情况下定义:
is a:抽象类 :有共同属性
like a:接口:没有共同属性,需同用一个方法,把方法抽取成接口
*多态:父类类型的引用指向了子类类型的对象。(向上转型)
-多态的前提条件:存在继承或者接口;
-多态的弊端:只能使用父类的功能;
-多态的好处:提高了程序的扩展性,前期定的功能可以被后期出现的事物使用;
*向下转型:强制类型转换;
*接口和多态,把接口看成一个类就行;
*多态中:非静态的方法:编译看父类,执行看子类(子类重写了方法)
静态的方法:编译执行都看父类;
模板设计模式:
*当实现一个功能时,功能的一部分是确定的,一部分是不确定的,确定的部分还会用到不确定的部分,那么久把不确定的部分暴露出去,让子类去实现。
内部类:(静态只能用静态的,非静态的都可以用)
*在一个类内部定义的类;
-内部类在成员的位置,看成成员内部类;成员和成员之间可以直接使用,所以可以直接使用外部类的成员变量;
内部类是非静态的时候:Outer.Inner inner =new Outer().new Inner()
内部类是静态的时候:Outer.Inner inner =new Outer.Inner()
inner.show()//show不是静态的,所以inner要创建对象。这时候不用创Outer,因为Inner是静态的
如果show是静态的:Outer.Inner.show();
-如果一个内部类有静态的成员方法,那么该内部类必须是静态的
-内部类得到外部类对象:外部类名.this;
-局部内部类:在方法内部定义的类,用到其所在函数的局部变量,该局部变量必须是最终的final;
*匿名内部类:new对象或接口,作为类型传递
*异常:程序在运行时出现的不正常情况。由来:java把程序在运行时出现的不正常情况也看成了对象;提取属性进行描述。(比如异常名,信息、位置)从而形成了各种异常类。
-异常的分类:Throwable(子类Error和Exception)
一类是严重的问题:Error:一般不用写针对性的代码进行处理
一类是不严重的问题:Exception:要写针对性代码进行处理
-throws:声明函数可能发生异常,那么调用者必须处理!
- try (){}catch{}子类异常要写在父类异常的上边!
-throw new FuShuException();系统自动抛异常系统自带的异常,自定义的异常类对象需要手动throw异常,这时候必须处理(声明或抛出)。一般自己声明异常,让调用者处理(选择抛出还是捕获);
-当异常是RuntimeException时,内部使用throw抛出,不用处理,编译通过,使用throws声明抛出,也不用处理,编译也通过;运行时异常,抛出或者声明了也不用处理;
-异常分为两类:
一类是编译时不检测的异常RuntimeException或其子类,
一类是编译时检测的异常:非RuntimeException或其子类;
-运行时异常通常都是因为用户传递了错误的数据造成的,java认为当遇到运行时异常时,程序就给中断,不该处理。
*String类;如果重写了object中的String类,那么比较的是两个字符串中的内容。而“==”在引用类型中比较的是地址值;
*StringBuilder出现原因: 1、提高效率 2、提高安全性 3、简化书写
*集合的好处:可以存储不同类型的对象,而却会随着元素的增加而自动增大容量。
- 为什么有这么多的集合类?每种集合存储数据的方式不同,也就是底层使用的数据结果是不同的。
*Iterator在迭代的过程中如果用集合进行删除或者其他操作会出现迭代异常;只能使用iterator的删除方法,it.remove();并且只有这一个方法
*ListIterator解决了Iterator功能少的问题,该迭代器可以在迭代的过程中用ListIterator对list进行增加,修改,删除!
迭代器其实就是collection的每个集合的内部类。
*集合中contains判断的是否包含某个对象的一句是boolean equals(Object obj)方法,所以在要比较的对象中重写equals方法,当属性一样,返回true
*TreeSet可以让自身集合排序,默认也可以排序,默认按字典顺序。(依据的是String 类的compareTo()方法)和基本数据类型都可以自动比!
当排序主要条件相同时,要指明排序的次要条件
-int num = this.age-age==0 ;
-int num2 =this.name.compareTo(name)?num2:num;
*TreeSet比较器:
1:让元素自身具备比较性,需要元素对象实现Comparable接口,覆盖compareTo方法。
2:让集合自身具备比较性,需要定义一个实现了Comparator接口的比较器,并覆盖compare方法,并将该类对象作为实际参数传递给TreeSet集合的构造函数。
-泛型:把运行时期的异常转移到了编译时期,提高了程序的安全性;不用强制类型转换了
泛型插除:泛型是在编译时期使用的,编译后的class文件中是没有泛型的!
泛型用在类上,在创建类后面添加一个<E>
泛型用在方法的参数上:方法的参数类型只有在类上的泛型确定了才能确定。方法需要定义成泛型方法。ClassA<E>{Public void show(E arg){}}
如果一个方法的参数的类型可以是任意类型,那么该方法自己使用泛型(类不设置):public <E> void fun(T args){};
静态方法只能自己用泛型,因为在对象还没创建的时候就加载了;
public static<E> void fun(Targs){};
Map遍历方式:
A:keySet
B:entrySet:Map.Entry<>;是定义在Map集合内的静态方法,是键值对的映射关系的体现。
*把数组转成字符串的:
int[] arr = {23,34,45,56,45};
String str = Arrays.toString(arr);
*把数组转成集合
String[]ss = {“haha”, “hehe”, “xixi”, “gaga” };
List<String>list =Arrays.asList(ss);
这个集合不能进行添加或删除;但可以修改(list.set(2,“heihei”))!
为什么要数组转集合?集合的方法多!
*把集合转成数组
String[]arr = list.toArray(new String[list.seze()]);
为什么集合转数组?因为数组的长度是固定的,当不允许用户添加删除时,可以集合转数组。
*Collections
对List数组进行自定义排序及排序
Collections.sort(list);//排序(可比较)
Collections.sort(list,Collections.reverseOrder());//反序比较
Collections.sort(list,newmyComparetor());//myComparetor()是自定义的比较器,继承自Comparetor
Collections.sort(list,newCollections.reverseOrder(myComparetor()));
//按照自定义比较的反序比较
Collections.,max(list);//最大值
*增强for:只能遍历数组或Collection集合;map专窗set后用这个
*可变参数:必须作为参数列表的最后一个参数(封装成了数组)
*静态导入:例子:import staticjava.util.Arrays.*;
静态导入导的是方法,还是要导包的;
*Runtime类;每个java运行时都有一个运行时类的对象;
Runtime rt =Runtime.getRuntime();
rt.exec(“notepad”);
rt.exit();
*多线程可以实现同一个程序中不同功能或相同功能同时执行的效果;
线程是随着任务的存在而存在,随着任务的执行完成而消失。
主线程代码写在main方法中,自定义线程的任务代码写在run方法内;
*run()方法知识一个普通的方法调用,不具备启动线程的功能,而start()方法会启动一个线程并自动去执行run()方法中的代码;
*线程异常只会影响线程所在的线程,是它自己的事,并不会对其他线程造成影响。
*线程两种实现方式:
A:实现runnable;线程任务和线程对象进行了分离,线程执行什么任务就不再重要了,只要是实现了Runnable接口的子类对象就可以作为参数传递给线程的构造方法。(创建一个类,就是一个任务,不用同步)(推荐使用)线程有Thread创建,而这个类只考虑任务就好了!它在实现Runnable的接口同时还可以继承父类;
B:继承自Thread的类,该类是线程类的同时,还要定义任务。(不一定同步)
同步代码块带来线程的安全性;缺陷:没有得到的锁的线程会反复判断锁;
锁的对象: 代码块:任意对象;方法:this;静态方法:类名.class
*线程间的通信:多个线程执行的任务不同,但是操作的资源相同。
*等待唤醒机制:obj.notify();唤醒对方—允许空唤醒。(obj.wait())
Wait();notify();notifyAll();这些方法必须用在同步中,因为同步中才有锁,这些方法是当前持有锁的线程区等待或唤醒!
wait():让线程进入等待状态,吧线程放入了线程池;notify():唤醒线程池中的任意一个线程;notifyAll():唤醒线程池中的所有线程
interrupt();强制结束线程的等待!
生产者消费者:一个生产线程,一个消费线程,程序运行没有问题;
当有多个线程:多个生产线程,多个消费线程,程序运行有问题出现了,生产多次,消费一次,或者生产一次消费多次的情况;出现的原因是:当一个线程被唤醒没有回去判断标记,直接执行下面的代码,导致不该生产也生产了不该消费也消费了
解决方式:把if()判断改为while()循环
把if判断改为while()循环,出现了死锁,
死锁的原因是:当线程唤醒的是本方线程时,导致所有线程全部等待
解决死锁的方法是:notify唤醒的是线程池中任意一个线程,不能保证唤醒的是对方线程。Jdk1.5之前把notify()改为notifyAll();这时候把不该唤醒的线程也被唤醒了,导致程序性能降低。
解决:java.util.concurrent.locks;jdk1.5之前对锁的操作是隐式的:用synchronized(){ } ;任何对象都可以当锁,没有把锁面向对象化
Jdk1.5之后,对锁进行了单独的描述—使用的是Lock接口
使用Lock来替代同步代码块
1:创建一把锁,使用Lock接口的子类ReentrantLock
Lock lock = new ReentrantLock();
创建锁:lock.lock();释放锁:lock.unlock();释放锁一般放在finally内。
2:把需要同步的代码块放在lock()和unlock();
把同步代码块替换成Lock之后,出现了异常;就是wait(),notify(),notifyAll()都不能用了,它们只能在同步代码块中使用;而同步没有了所以异常。
有个对唤醒对待方法进行单独描述的接口Condition;这些方法必须结合相应的锁,使用Lock的newCondition()方法来获得和锁相关联的Condition的对象
Conditioncon =lock.newCondition();等待:con.await();con.signal();
使用Lock()中的方法代替;await();hesignal();signalAll();
*一个锁Lock可以得到很多个Condition;通过对它的分组来提高性能!比如生产线程一个Condition,所有的消费线程用一个Condition。
*守护线程:t.setDaemon(true)设置为守护线程看成后台线程,依赖于前台线程。前台线程结束后,守护线程自动结束。
* t.join();加入运行,提高它的优先级。先启动线程后在join(),主线程一定在join()线程完全完成后才开始运行,对于其他线程只是提高优先级;
*线程池(android):含有多个线程的池子,可以创建线程
单个线程的线程池:
-ExecutorService es =Executors.newSingleThread();任务是顺序执行的,执行完一个后再执行下一个
*并发执行 固定线程数的线程池对象
-ExecutorService es = Executors.newFixedThread(2);//固定最多2个线程;
-es.execute(thread1); es.execute(thread2);
任务数量和线程数量相同时,任务被同时执行;11,22,11,22,
任务数量大于线程数量时,两个任务同时执行,剩下的空下来的已创建一个线程区执行它;
*缓冲线程池
ExecutorService es = Executors.newCachedThreadPool();
自身会创建一定数量的线程的线程池,线程数量大于任务数量,会自动销毁空闲的线程。当任务数量增加是,会增加线程的数量;
*缓冲线程池
创建数量无限的线程池对象,空闲的线程也不会被销毁
ExecutorService es = Executors.newScheduledThreadPool();
*匿名内部类创建线程
1、new Thread(){
Public voidrun(){}}.start();
*获取系统平台下的换行符;
*装饰设计模式:基于已经存在的功能提供增强的功能
每个子类都加缓冲功能,子类太多,导致添加缓冲功能太多,这时候把这个功能提取出来,封装成一个类,谁用就把谁作为参数传递!
特点:1、使原有体系变得简单了
2、装饰类是在原有功能的基础上提供了增强的功能,所以还属于原有体系。。
*文件过滤器FilenameFilter
File[] files = file. (
new FileterByName(“.txt”));
*class FileterByName implements FilenameFilter{
PrivateString;
PublicFileterByName(ends){
This.ends=ends}
Publicboolean accept(File dir,String filename){
if(filename.endWith(ends)){
returntrue;}
` else{
Return false}
} }
*Properties:继承了HashTable;属于Map集合;键和值都是string类型,它是集合中可以和流配合使用的集合;多用于属性文件,的配置!!!
Propertiespro =new Properties();
Pro.setProperty(“name”,“zhangsan”);
Pro.setProperty(“age”,“23”);
Set<String> keys = pro.getStringPropertyName();
//得到所有属性名的集合根据键找值。。。
value=pro.getProperty(key);
----->以上都是在内存中,关机断点后数据都会消失
-FileReaderfr =new FileReader(“config.properties”);
-pro.load(fr);//读文件,把文件中的键值对存到集合中;
-pro.setProperty(“color”,“green”);//在内存中的修改,不作数的
-FileWriterfw = new FileWriter(“config.properties”);
-fr.close;f2.close();
*printStream:字节打印流
*printWriter:字符打印流
*序列流:多个文件合并写到一个文件中:SequenceInputStream;
*枚举的获取;A:用vector:v.elements();
B:用Collections.enumeration(list);
- 把一个文件拆成多个文件;
*把对象进行持久化存储,需要对对象进行序列化(对象必须实现Serializable接口) :看不了,只能用ObjectInputStream();readObject();//把持久化存储对象读取出来,叫做反序列化;对象时依赖于其所属的类的,能够反序列化,必须有其序列化所属的字节码文件对象;
对象流读和取都依赖于Student.class;如果没有对象类,会报nofoundclass异常,如果不添加序列号,改变class文件后,自动添加的序列号会变;所以最好自己写一个序列号;staticfinal Long serialVersionUID=33L;
Privatetransient String name;//使成员不参与序列化存储;使用transient修饰;
ObjectOutputStreamoos = new ObjectOutputStream(new FileOutputStream(object.txt));
-oos.writeObject(newStudent(“haha”,22));
*RandomAccessFile:随机访问文件,不属于IO体系,只能访问文件
内部既有字节输入流,也有字节输出流
内部有字节数组,并使用指针来操作该数组,所以能实现随机访问文件。
*数据流DataOutputStream();DataInputStream();
*内存流:从内存中读,向内存中写ByteArrayInputStream;
ByteArrayOutputStream;
ByteArrayInputStream:必须接受一个字节类型的数组,是从该字节数组中读,而该数组在内存中,所以是从内存中读;
ByteArrayOutputStream:往内存中写入数据;该流类内部定义了一个字节数组;
*转换流的编码问题:构造,第二个参数就是编码格式;
写入是编码:byte[] getBytes();使用平台默认的字符集将此编码为的byte序列;并讲结果存储到一个新的byte数组中
byte[]getBytes(Charset charset);使用给定的charset将此编码为的byte序列;并讲结果存储到一个新的byte数组中
读取时解码:
String(byte[]bytes):解码
String(byte[]bytes,Charsetcharset);指定解码
网络编程
IP地址:本机:127.0.0.1
端口:数字标识 0-65535;1024以内是系统自身使用(指发到对方的端口)
InetAddress.getByName("10.0.159.180")这时候作为参数
System.out.println(s.getInetAddress().getHostAddress()+"连接到服务器");