面向对象
1.继承:是类和类之间的关系,继承与对象无关。
子类无条件拥有父类中所有“可继承”的属性和方法。(构造方法不可继承)
Override方法重写:
(1). 方法名要与父类相同。
(2). 返回值类型也要相同
(3). 参数列表也要相同
注意:子类重写父类方法时,方法中的访问修饰符必须大于等于父类中方法的修饰符。
Public>protected>默认>private
继承的注意点:
(1). 不要为了仅仅只是得到某个类的成员而去继承,不要为了继承而继承。(比如人和狗都有名字和年龄,不能相提并论,必须同一个类,或者说是同一个物种)
(2). 只要有一个成员或方法不是所有子类都拥有的,那么这个成员属性和方法就不应该定义在父类中。
构造方法的作用:为即将创建对象的属性实现‘显示初始化’,构造方法返回对象就创建成功了
父类如果没有特殊需求,在类中最好提供以一个‘空参’构造方法,目的就是为了方便子类的创建。
2.多态的引入:
定义:父类的引用指向子类的对象;
多态的第一种使用场景:方法的参数设计上,如果设计一个方法,尽量将方法的参数设计为“父类类型”,因为父类类型的参数可以接收所有其“子类对象”。
多态的第二种使用场景:创建子类对象,使用父类引用接收,提升代码的维护性。
程序中为何使用向下转型:
为了使用子类的特有的“属性和行为”。Instanceof实例对象类型判断。
final关键字:final最终化,不可再次更改的含义。
final修饰方法的作用:允许子类使用,但是不允许子类重写
Final修饰类:被final修饰的类不能被继承。
final修饰属性:属性在定义的同时必须进行初始化。因为属性有默认初始值。
知识点:补充
3.抽象类:(抽象的对象,new不出来滴,看业务需求是怎样的,可以想想饿了么,user是不能new出来的)
抽象类:父类要给所有子类定义“行为规范”
(1). 可以定义抽象方法
(2) 也可以定义非抽象方法(拥有方法体的方法)
(3). 当然也可以定义属性
(4) 抽象类也是类,所有也拥有构造方法
描述:
1). 没有方法体的方法必须定义为“抽象方法”。抽象方法使用abstract关键字修饰
2). 拥有抽象方法的类,必须被定义“抽象类”
3). 不能实例化抽象类的对象
4). 子类要new对象的话,那就必须实现父类的所有抽象方法
5). 抽象创建对象?抽象类中的抽象方法,缺少方法体,因此调用抽象方法“毫无意义”。
使用规则:看顶层,创建子类对象,使用顶层定义的行为规则。
抽象类补充:
Abstract关键字不能和哪些修饰符共同使用??
抽象方法:父类给所有的子类定义了行为规则,这个行为是父类要求子类必须实现。
Final代表最终,不可以修改,不可修改子类就无法实现重写。
Static修饰的方法可以直接使用类名调用;抽象方法没有实现体,调用毫无意义。
Private:私有化,对内开放,对外保护,子类也是保护的,不能直接使用。
(接口:可扩展性 完全解耦 美滋滋 ,个人有个人独立的操作,互不相干,比如饿了么的流程)
4.接口:给所有想要该功能的类定义了行为规范
1. 程序中一方使用规则,另一方实现规则,那么此时双方就可以实现通讯。
2. 接口为类实现了功能的扩展
3. 程序就实现了解耦
接口与抽象类的区别??
(1). 抽象类可以定义抽象和非抽象方法,但是,接口只能定义抽象方法。
(2). 抽象类依然是类的继承体系,拥有构造方法。构造方法的作用是用来初始化该对象的属性。接口没有构造方法。因此,接口中的所有数据必须定义为常量。
(3). 抽象类中的抽象方法是为了所有的子类定义的行为规则。接口中的抽象方法是为了所有需要该功能的类定义行为规范。
(4). 抽象类中所有属性与行为都可以被子类继承。类似于整个结构中的数据与功能。接口就类似于类的扩展功能,给类增加了一些额外功能。属于类继承体系之外的功能。
5.内部类引入
特点:
(1). 在成员内部类中可以访问外部类的所有成员(人与心脏)
(2). 成员内部类中的方法也可以调用外部类的方法
(3). 成员内部类中不可以声明静态变量,静态方法。因为成员变量是属于对象的,静态与对象无关。
(4). 外部类中可以用内部类声明成员属性,作为外部类的成员。也可以在方法中创建内部类对象,调用内部类的方法。
成员内部类,会随着对象的创建而加载。
静态内部类:会随着外部类的加载而加载
(1). 在静态内部类中只能访问外部类的静态成员。
(2). 在静态内部类中可以定义静态成员和非静态成员,而在成员内部类中不允许定义静态的成员。
(3). 在静态内部类的方法中不可以调用外部类的对象方法,但是可以调用外部类的静态方法。
***匿名内部类***:
语法:(比如临时工什么的,就是临时定义一个对象啥的)
New USB(){} 表示具体的实现体。接口缺少抽象方法的实现体。我们可以在{}中完成抽象方法的实现体。
一些补充:
new关键字的作用:
a. 在堆区开辟空间
b. 给开辟空间的属性进行默认初始化
c. 返回堆区开辟空间的首地址
对于重写Object中的方法
a. 重写equals目的:自定义子类对象的判断规则。
b. 重写toString目的:自定义对象的输出数据
补充:对象都应该根据判断数据内容来判断,为什么Object类不知道这么一个简单的原理呢?
Object类根本不知道子类的具体数据,无法做出数据的判断
静态属性,非静态属性区分:
如果一个属性是每一个对象独有的,不能产生混乱。
那么这个属性就必须定义为“非静态属性”。
(堆区空间的大小取决与“非静态区”中的属性多少
非静态区中到的所有属性都会在new对象时,被复制一份存储到堆区。)
补充:一个类在整个程序运行时,仅会被加载一次
6.静态区的属性特点:
a. 对象创建时,不会复制静态区中的属性
b. 静态区中的属性仅有一份,而且可以被该类的所有对象访问。
静态定义:
如果一个方法不需要使用对象的数据,那么该方法就应该被设计为“静态方法”。
(上述条件如果不定义为静态:
a. 浪费堆区中的空间
b. 降低了程序的性能)
好处:
a. 节省内存
b. 执行效率比非静态方法高。
补充:静态方法中没有this关键字,因此无法获取对象的数据。(压根儿就跟对象没关系)
Exception(异常):
Java虚拟机处理异常的方式:
1. 调用异常对象的printStackTrace()打印堆栈调用信息
2. 提前终止程序 System.exit(...);
当异常抛回的时候,调用者没有做任何处理,此时,程序会继续向上抛, 考虑:谁调用了main方法??Java虚拟机
结束程序的两种方式:
1. main方法返回
2. 异常交给虚拟机处理
异常包含了“异常名称,异常出错的数值,异常发生的代码位置”,程序的调用堆栈信息...如此多的信息,程序将这些信息封装成了一个“异常”对象,将该异常对象抛回给调用者。
手动抛出异常
格式:throw new 异常对象(...);
运行时异常的处理方案:
1. 不处理,异常最终会抛给虚拟机,程序提前终止
2. 捕获处理 try-catch
合并唯一:如RuntimeException或者统一Exception
开发中常用后者。
编译时期的异常如何处理???
编译时期异常的特点:
无论代码是否正确,编译器都会报错
处理方法:
方案1:throws声明异常(方法)
----》如果声明的异常的方法发生异常,请找调用他的人处理。
方案2:异常捕获try-catch
一旦捕获,无论如何处理,程序都会正常终止。
说明:如果catch捕获异常,但是没有捕获到发生异常
类型,最终该异常会继续抛出给方法的调用者,最终这样的
效果就类似于没有捕获。
Try-catch-finally finally块到底有何用??
Finally可以在catch语句return之前,关闭开辟的资源
作用:无论try语句中是否发生异常,finally语句都会被执行。
哪怕catch语句中存在return语句,return之前先要执行finally代码块。
异常使用注意细节:
Throw关键字之后不可以直接编写任何代码。
可以间接编写代码
如果一个方法中抛出了编译时期异常,那么该方法必须声明该异常
子类重写父类方法时,如果内部发生了异常,只能自己try-catch...(自我理解。也就是说,父类的被继承和接口的被实现,如果父类或者接口未声明异常,则需要子类自己去try-catch,否则报错)
正则表达式:
1. []:数据的范围 [0-9] \\d + 一次或更多 {1,}
2. {}:前面数据出现的次数 {4,11}{4,}{4} * 0次或更多 {0,}
3. ():分组.默认编号,自增。(从1自动开始自增)
? 0次或一次 {0,1}
4. Mathces(String regex),,split(String,regex),replaceAll(String regex ,String replacement)
包装类引出
基本数据类型不是类,所以基本数据类型没有属性和方法
Java语言为基本数据提供一个对应的包装类
包装类:为了给基本数据类型提供更多的数据和行为。
补充://IntegerCache 整型包装类缓存
缓存范围[-128-127]返回的是缓存中的对象,如果超过这个范围,此时就会new一个新包装对象返回。
Integer i = 127;Integer i2 = 127; ---->i1=i2 true
Integer i3 = 128;Integer i4 = 128; ---->i3=i4 flase
(注意:上述包含了一个自动装箱)
Math几个静态方法
Math :数学类
abs 绝对值 Math.abs(-98); 98
ceil(向上取整) Math.Ceil(8.1); 9.0
floor(向下取整)Math.Floor(8.9); 8.0
round:四舍五入 Math.Round(8.4); 8.0
max:最大值 Math.max(20,50); 50
min:最小值 Math.min(20,50); 20
pow:次幂 Math.pow(10,3); 1000.0
random:随机数(0.0~1.0) int num = (int)(Math.random*100;32
Arrays数组工具类:
toString 输出数组,以字符串的形式
Soft 排序
Date日期类:
常用的编写代码
Date date = new Date();
//date 表示当前日期 + 时间
//如何构造时,传入“毫秒数”.这个一个从标准时间开
始计算的日期 1000*60*60*24
//1970年1月1 00:00 :00 中国: 东八区08:00:00
getTime setTime
DateFormat类
格式化:format
第一种默认格式:DateFormat df = new SimpleDateFormat();
第二种自定义格式:DateFormat df2 = new SimpleDateFormat(“yyyy年MM月dd HH:mm:ss”);(自定义格式也是可以的)
DateFormat df3 = new SimpleDateFormat(HH:mm:ss);
String date_now = df3.format(new Date());可以单独得到现在时间
String date_str = df.format(new Date());
String date_str2 = df2.format(new Date());
解析:parse String str = “2111年11月11 11:11:11”
Date date = df.parse(str);
解析的前提必须传入解析的模式pattern
DateFormat df2 = new SimpleDateFormat(“yyyy年MM月dd HH:mm:ss”);
Calendar类:
Calendar rigthNow = Calendar.getInstance();
//以此可以获取年月日 field 属性/字段
rightNow.get(Calendar.YEAR); 获取年
rightNow.get(Calendar.MONTH); 获取月 (0~11)
rightNow.get(Calendar.DAY_OF_MONTH); 获取日
rightNow.set(Calendar.YEAR,2008); //设置年
rightNow.add(Calendar.YEAR,10); //去到十年后
rightNow.add(Calendar.MONTH,-5); //去到五个月之前
For each :高级循环 底层是迭代器
可变参数:
计算多个数据求和:
Public static int getNum(int... array){
Int sum = 0;
for(int i = 0;i<array.length;i++){
sum+= array[i];
}
return sum;
}
补充:可变参数的底层实现就是数组,两个方法完全重复
注意:指定的int类型可变参数必须位于最后一个形参
Collection接口:
List:有序,可重复 set:无序,不可重复
ArrayList为什么有两个抽象的父类???
说明:ArrayList的两个父类没有实现全部“接口中的方法”
剩余的方法,由ArrayList类进行实现,由于ArrayList继承了
父类中实现的其余方法,因此ArrayList实现类,可以调用
接口中的所有方法。
注意:集合只能存储引用类型,不能存储基本数据类型。
跌代器的引入:
Forech跌代:
for(元素类型(type) 变量名:数组/集合){
在内部直接操作“变量名”(元素对象)
}
Iterator 跌代 :hasNext();
next();
remove();
就这三个方法,使用for each和iterator这个,看是否会操作一些数据。for each是办法单独操作数据的.
listIterator:列表跌代器
可以实现增删改操作
跌代操作可以实现特有的逆向跌代操作。但注意列表
迭代器的光标位置(逆向需要设置光标位置)
Previous 返回前一个元素
注意***:
1. NoSuchElementException 没有这个元素异常
原因:一个hasNext()方法只应该对应一个next()方法
2. ConcurrentMdificationException 并发修改异常
并发:多个对象同时操作一份数据
原因:如果跌代器在跌代集合元素,迭代器可以删除元素,
但是集合不可以进行增删改的操作
跌代器在跌代同时,集合如果进行增删改操作立刻发生并发修改异常。
泛型的引入:如: K V E T
泛型就是参数化类型
以传递参数的方式确定类中具体泛型的类型
注意:::******
方法的参数类型是集合类型
程序编译后,会将集合类型上的泛型擦除,此时两个方法都是集合类型,所有方法名和类型重复了
不允许同时存在。
通配符 ?:
?Super Student 翻译:我不知道是什么类型,但是这个类型它的父类类型为Student(下线限定)
?可以传递Student,或者传递Student类的父类对象。
Student extends Person
? extends Animal 翻译:我不知道是什么类型,但是这个类型继承自Animal类型。
?可以传递Animal,或者传递Animals类的子类的对象。
泛型的作用与优势:
1. 泛型可以确定集合中存储元素的统一类型
2. 泛型可以将运行阶段可以发生的类型转换异常提前到编译阶段进行语法检查。
3. 泛型解决了元素类型强转的问题
泛型补充:(泛型已经成为编写代码的规范)
1.泛型只支持引用数据类型(类类型或接口类型等),泛型不支持基本数据类型。
2.泛型不支持数据类型以继承的形式存在,要求前后泛型的数据类型必须一致。
Arrlist集合存储自定义对象
想要解决重复元素的问题
那么自定义对象需要重写equals方法
原因:ArrList类中的contains方法
依赖与自定义对象equals方法
待续....................