java学习笔记-面向对象总结(二)
面向对象本质
标签:核心总结
本人学习总结
this 本质
- this的本质就是“创建好的对象的地址”! this不能用于static方法中。
构造方法:
- 构造方法的作用是为创建对象进行初始化工作,比如给成员变量赋值
- 构造方法与类同名,不能书写返回值类型
- 构造方法的第一条语句如果是super(),则可以省略,该语句作用是调用父类无参数的构造方法
- 调用顺序:
1、 先向上追溯到Object,然后在依次向下执行类的初始化和构造方法,直到当前子类为止;
2、 静态初始化块与上述相同;
类方法:
- 在类方法中调用本类的类方法时可直接调用
继承:
- 子类继承父类全部的属性和方法(除了父类的构造方法),但不见的子类可以访问父类的私有属性和方法。
重写:
- 方法的重写:
1、“==” 同名同参
2、“<=”返回值类型,声明异常,子类的要小于父类
3、">="访问权限子类大于父等于父类
高内聚低耦合
高内聚:类的内部操作细节自己完成,不允许外部干涉
低耦合:尽量避免暴露少的方法细节给外部使用,尽量方便外部调用
访问修饰符
对象的转型
向上:(自动转型)
fianl关键字作用:
- 修饰变量不可修改
- 修饰方法不能重写,可以重载
- 修饰类,类不可以被继承
抽象类
- 抽象类可以包括属性、方法、构造方法
- 抽象类只能被继承
- 必须被子类实现
为什么需要接口,接口和抽象类的区别
-
接口就是比“抽象类”还“抽象”的“抽象类”,可以更加规范的对子类进行约束。全面地专业地实现了:规范和具体实现的分离。
-
抽象类还提供某些具体实现,接口不提供任何实现,接口中所有方法都是抽象方法。接口是完全面向规范的,规定了一批类具有的公共方法规范。
-
从接口的实现者角度看,接口定义了可以向外部提供的服务。
-
接口是两个模块之间通信的标准,通信的规范。如果能把你要设计的模块之间的接口定义好,就相当于完成了系统的设计大纲,剩下的就是添砖加瓦的具体实现了。大家在工作以后,做系统时往往就是使用“面向接口”的思想来设计系统。
-
接口和实现类不是父子关系,是实现规则的关系。比如:我定义一个接口Runnable,Car实现它就能在地上跑,Train实现它也能在地上跑,飞机实现它也能在地上跑。就是说,如果它是交通工具,就一定能跑,但是一定要实现Runnable接口。
接口的本质:
-
接口就是规范,定义的是一组规则,体现了现实世界中“如果你是…则必须能…”的思想。如果你是天使,则必须能飞。如果你是汽车,则必须能跑。如果你是好人,则必须能干掉坏人;如果你是坏人,则必须欺负好人。
-
接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守。
-
面向对象的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么我们讨论设计模式都只针对具备了抽象能力的语言(比如C++、Java、C#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。
-
接口和抽象类区别:
1、普通类:具体实现
2、抽象类:具体实现,规范(抽象方法)
3、接口:规范(契约)
定义接口的详细说明:
- 只能是public或者默认。
- 接口名:和类同级。
- extends:可以多继承
- 常量:接口中的属性只能是常量,总之是public static final 修饰,不写也是。
- 方法:接口中的方法只能是public abstract,省略的话,也是public abstract。
要点:
-
子类通过implements来实现接口中的规范。
-
接口不能创建实例,但是可用于声明引用变量类型。
-
一个类实现了接口,必须实现接口中所有的方法,并且这些方法只能是public的。
-
JDK1.7之前,接口中只能包含静态常量、抽象方法,不能有普通属性、构造方法、普通方法。
-
JDK1.8后,接口中包含普通的静态方法。
内部类:
- 内部类可以使用public、default、protected 、private以及static修饰。而外部顶级类(我们以前接触的类)只能使用public和default修饰。
注意:内部类是一个编译时的概念,一蛋编译成功,就会成为两个完全不同的两个类。对于一个名为Outer的外部类和其内部定义的名为Inner的内部类。编译完成后会出现Outer.class和Outer$Inner.class两个类的字节码文件。所以内部类是相对独立的一种存在,其成员变量/方法名可以和外部类的相同。
内部类中可以声明与外部类同名的属性与方法
内部类的作用:
- 内部类提供了更好的封装,只让外部类直接访问,不允许同一个包中的其他类访问。
- 内部类可以直接访问外部类的私有属性,内部类被当成其外部类的成员,外部类不能访问内部类的属性。
- 接口只是解决了多重继承的问题,而内部类使得多重继承更加完整
内部类的使用场合:
- 由于内部类提供了更好的封装特性,并且可以很方便的访问外部类的属性。所以,在只为外部类提供服务的情况下可以优先考虑使用内部类。
- 使用内部类间接实现多继承:每个内部类都能独立地继承一个类或者实现某些接口,所以无论外部类是否已经继承了某个类或者实现了某些接口,对于内部类没有任何影响。
内部类的分类:
-
在Java中内部类主要分为成员内部类(非静态内部类、静态内部类)、匿名内部类、局部内部类。
-
成员内部类(可以使用private、default、protected、public任意进行修饰。 类文件:外部类$内部类.class)
-
非静态内部类(外部类里使用非静态内部类和平时使用其他类没什么不同)
i. 非静态内部类必须寄存在一个外部类对象里。因此,如果有一个非静态内部类对象那么一定存在对应的外部类对象。非静态内部类对象单独属于外部类的某个对象。
ii. 非静态内部类可以直接访问外部类的成员,但是外部类不能直接访问非静态内部类成员。
iii. 非静态内部类不能有静态方法、静态属性和静态初始化块。
iv. 外部类的静态方法、静态代码块不能访问非静态内部类,包括不能使用非静态内部类定义变量、创建实例。
v. 成员变量访问要点:- 内部类里方法的局部变量:变量名。
- 内部类属性:this.变量名。
- 外部类属性:外部类名.this.变量名。
-
静态内部类:
i.定义方式:static class Inner{}
ii. 当一个内部类对象存在,并不能保证外部类对象存在。因此静态内部类的实例对象并不能访问外部类的实例方法
内部类的访问:
- 外部类定义内部类 new Inner();
- 外部类以外的地方引用内部类:(先创建外部类实例,然后使用该外部类实例创建内部类实例)
Outer.Inner inner = new Outer().new Inner();
匿名内部类:
注意:
匿名内部类没有修饰符
匿名内部类没有构造方法,因为他连名字都没有何来构造方法。
局部内部类:
-
定义在方法内部的,作用域只限于本方法,称为局部内部类。
-
局部内部类的的使用主要是用来解决比较复杂的问题,想创建一个类来辅助我们的解决方案,到那时又不希望这个类是公共可用的,所以就产生了局部内部类。局部内部类和成员内部类一样被编译,只是它的作用域发生了改变,它只能在该方法中被使用,出了该方法就会失效。
-
局部内部类在实际开发中应用很少。
编译运行如下Java代码,输出结果是(D )--上转型对象无法使用对象的新增方法,只能使用继承或重写的方法
class Base {
public void method(){
System.out.print ("Base method");
}
}
class Child extends Base{
public void methodB(){
System.out.print ("Child methodB");
}
}
class Sample {
public static void main(String[] args) {
Base base= new Child();
base.methodB();
}
}
A.Base method
B.Child methodB
C.hild methodB
D.编译错误
继承条件下子类构造方法的执行过程。
(1)如果子类的构造方法中没有通过super显式调用父类的有参构造方法,也没有通过this显式调用自身的其他构造方法,则系统会默认先调用父类的无参构造方法。在这种情况下,写不写“super();”语句,效果是一样的;
(2)如果子类的构造方法中通过super显式调用父类的有参构造方法,那将执行父类相应构造方法,而不执行父类无参构造方法;
(3)如果子类的构造方法中通过this显式调用自身的其他构造方法,在相应构造方法中应用以上两条规则;
(4)特别注意的是,如果存在多级继承关系,在创建一个子类对象时,以上规则会多次向更高一级父类应用,一直到执行顶级父类Object类的无参构造方法为止;
Error和Exception区别:
- 1、你开车遇到一只猪,你刹车,这叫exception。
- 2、你开车,车坏了,这叫error
NumberFormatException异常
public class Test7 {
public static void main(String[] args) {
String str = "1234abcf";
System.out.println(Integer.parseInt(str));
}
}
执行结果如图6-8所示:
数字格式化异常的解决,可以引入正则表达式判断是否为数字:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test7 {
public static void main(String[] args) {
String str = "1234abcf";
Pattern p = Pattern.compile("^\\d+$");
Matcher m = p.matcher(str);
if (m.matches()) { // 如果str匹配代表数字的正则表达式,才会转换
System.out.println(Integer.parseInt(str));
}
}
}
已核查的异常CheckedException
- 所有不是RuntimeException的异常,统称为Checked Exception,又被称为“已检查异常”,如IOException、SQLException等以及用户自定义的Exception异常。 这类异常在编译时就必须做出处理,否则无法通过编译。