目录
一、Java面向对象学习的三条主线
1.Java类及类的成员: 属性、方法、构造器;代码块、内部类 2.面向对象的三大特征: 封装性、继承性、多态性、(抽象性) 3.其他关键字: this、super、static、final、abstract、interface、package、import等
二、解释面向对象和面向过程
(人把大象放冰箱):实体只有人,大象,冰箱
1.面向过程:强调的是功能行为,以函数为最小单位,考虑怎么做。 (1).打开冰箱 (2).抬起大象,塞进冰箱 (3).关闭冰箱 2.面向对象:强调具备了功能的对象,以类/对象为最小单位,考虑谁来做 人{ 打开(冰箱){ 冰箱.开开(); } 抬起(大象){ 大象.进入(冰箱); } 关闭(冰箱){ 冰箱.闭合(); } } 冰箱{ 开开(){} 闭合(){} } 大象{ 进入(冰箱){} }
三、面向对象的两个要素
类:对一类事物的描述,是抽象的,概念上的意思 对象:是实际存在的该类事物的每个个体,因而也称为实列 类和对象的使用: 1.创建类,设计类的成员 2.创建类的对象 3.通过"对象.属性"或"对象.方法"调用对象的结构 匿名对象: 1).理解:我们创建的对象,没有显示的赋给一个变量名,即为匿名对象 2).特征:匿名对象只能调用一次
一、类的成员之一:属性
属性(成员变量)VS 局部变量
二、类的成员之二:方法
四、方法
1)方法的重载:在同一个类中,允许存在一个以上的同名方法,只要他们的参数个数或者参数类型不同即可 “两同一不同”:同一个类,相同的方法名 参数列表不同:参数个数不同,参数类型不同 3.判断是否是重载:跟方法的权限修饰符,返回值类型,形参变量名,方法体都没有关系 4.在通过对象调用方法时:如何确定某一个指定的方法: 方法名==》参数列表 2)可变形参的方法 3)方法参数的值传递机制 4)递归方法:一个方法体内调用它自身
public class OverLoadTest {
public void getSum(int i,int j){
}
public void getSum(double d1, double d2){
}
public void getSum(String s, int i){
}
public void getSum(int i,String s){
}
//这种不可以
//com.git.java.javaOverLoad.OverLoadTest' 中定义 'getSum(int, int)'
// public void getSum(int m, int n){
//
// }
}
五、面向对象的特征一:封装性
封装:我们要封装的原因:我们程序设计追求“高内聚,低耦合”,类的内部数据操作细节自己完成,不允许外部干涉。仅对外暴露少量的方法用于使用。 封装,即隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别;将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体, 也就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中数据和函数都是类的成员。 面向对象的特征一:封装与隐藏 一、问题的引入; 加入额外的限制条件(private),这个条件就不能在属性声明时体现,我们只能通过方法(getLegs)进行限制条件的添加(setLegs) 二、封装性的体现: 我们将类的属性私有化,同时,提供公共的方(public)法来获取(getXXX)和设置(setXXX)此属性的值 三、封装性的体现,需要权限修饰符来配合 1.Java规定的4中权限(从小到大排列),private(只能在类当中使用)、缺省(在类和当前包中使用)、protected(在类和当前包和不同包使用)、public(同一个工程) 2.4中权限可以用来修饰类及类的内部结构:属性、方法、构造器、内部类 3.具体的:4中权限可以用来修饰类及类的内部结构:属性、方法、构造器、内部类 修饰类的话:只能使用:缺省、public、 总结封装性:Java提供了4中权限修饰符来修饰类及类的内部结构,体现类集类的内部结构在被调用时的可见性的大小。
public class AnimalTest {
public static void main(String[] args) {
Animal a = new Animal();
a.name="大黄";
a.age=1;
//a.legs=4;
a.setLegs(6);
a.show();
a.setLegs(7);
//a.legs=-4;用了private时不可直接调用
a.show();
}
}
class Animal{
String name;
int age;
private int legs;//腿的个数,不能直接看到legs这个属性
//对legs进行赋值
public void setLegs(int l){
legs=l;
if(l>=0 && l%2==0){
legs=l;
}else{
legs=0;
}
}
//对legs进行获取
public int getLegs(){
return legs;
}
public void eat(){
System.out.println("动物进食:");
}
public void show(){
System.out.println("name="+name+",age="+age+",legs="+legs);
}
}
六、构造器
一、构造器的作用: 1.创建对象 2.初始化对象的信息 二、说明: 1.如果没有显示的定义类的构造器的话,则系统默认提供一个空参的构造器 2.定义构造器的格式:权限修饰符 类名(形参列表){} 3.一个类中定义的多个构造器,彼此构成重载 4.一旦沃恩显示的定义了类的构造器之后,系统就不再提供默认的空参构造器
public class PersonTest1 {
public static void main(String[] args) {
//创建类的对象
Person1 p1 = new Person1();//new+构造器
p1.eat();
Person1 p2 = new Person1("李星云");
System.out.println(p2.name);
Person1 p3 = new Person1("王也",17);
System.out.println(p3.name+"\t"+p3.age);
}
}
class Person1{
//属性
String name;
int age;
//构造器
public Person1(){
}
public Person1(String n){
name=n;
}
public Person1(String n,int a){
name=n;
age=a;
}
//方法
public void eat(){
System.out.println("人吃饭");
}
public void study(){
System.out.println("人可以学习");
}
}
总结:属性赋值的先后顺序 1.默认初始化 2.显式初始化 3.构造器中赋值 4.通过“对象.方法”或“对象.属性”的方式,赋值 以上操作的先后顺序:1-->2-->3-->4
七、this关键字的作用
1.this可以用来修饰:属性、方法、构造器 2.this修饰属性和方法: this理解为:当前对象或正在创建的对象 2.1在类的方法中:我们可以使用“this.属性”或“this.方法”的形式,调用当前对象属性或方法,但是 通常情况下,我们都选择省略“this.“,特殊情况下,如果方法的形参和类的属性同名时,我们必须显示的使用"this.变量"的方式,表明此变量时属性,而非形参 2.2在类的方法中:我们可以使用“this.属性”或“this.方法”的形式,调用当前对象正在创建的属性或方法,但是 通常情况下,我们都选择省略“this.“,特殊情况下,如果方法的形参和类的属性同名时,我们必须显示的使用"this.变量"的方式,表明此变量时属性,而非形参 3.this调用构造器 1.我们在类的构造器中,可以显示的使用”this(形参列表)“方式,调用本类中指定的其他构造器 2.构造器中不能通过”this(形参列表)“方式调用自己 3.如果一个类中有n个构造器,最多只有n-1构造器中使用了"this(形参列表)" 4.”this(形参列表)"必须放在当前构造器的首行 5.构造器内部最多只能声明一个"this(形参列表)",用来调用其他的构造器
public class PersonTest2 {
public static void main(String[] args) {
Person2 p1 = new Person2();
p1.setAge(15);
System.out.println("age="+ p1.getAge());
p1.eat();
}
}
class Person2{
private String name;
private int age;
public Person2(){
this.eat();
}
public Person2(String name){
this();
this.name=name;
}
public Person2(int age){
this();
this.age=age;
}
public Person2(String name,int age){
this(age);
this.name=name;
this.age=age;
}
public void setAge(int age){//因为属性和形参同名了,加上this用来区分,this.属性名
this.age=age;
}
public int getAge(){
return age;
}
public void setName(String name){
this.name=name;
}
public String getName(){
return name;
}
public void eat(){
System.out.println("人吃饭");
}
public void study(){
System.out.println("人学习");
}
}
八、package和import的使用
一、package关键字的使用: 1.为了更好的实现项目中类的管理,提供包的概念 2.使用package声明类或接口所属的包,声明在源文件的首行 3.包,属于标识符,遵循标识符的命名规则、规范、”见名知意“ 4.每”.“一次,就代表一层文件目录 补充:同一个包下,不能命名同名的接口,类,不同的包下可以命名 二、import关键字的使用 import:导入 1.在源文件中显示的使用import结构导入指定包下的类、借楼 2.声明在报的声明和类的声明之间 3.如果需要带入多个结构,则并列写出即可(import java.util.*;) 4.如果使用的类或接口是java.lang包下定义的,则可以省略import结构 5.如果使用的类或接口是本包下定义的,则可以省略import结构 7.如果在源文件中使用了不同包下的同名的类,则必须至少有一个类需要以全类名的方式显示(com.git.java.javaEncapsulation.-----) 三、在设计时遵循视图层,控制层,模型层
九、面向对象的特征之二:继承性
继承:如果一个类A继承自另一个类B,就把这个A称为"B的子类",而把B称为"A的父类"。继承可以使得子类具有父类的各种属性和方法, 而不需要再次编写相同的代码。在令子类继承父类的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类的原有属性和方法,使其获得与父类不同的功能。 另外,为子类追加新的属性和方法也是常见的做法。 一、继承的好处: 1.减少代码的冗余,提高了代码的复用性 2.便于功能的扩展 3.为之后多态性的使用,提供了前提 二、继承性的格式:class A extends B{} A:子类、派生类、subclass B:父类、超类、基类、superclass 2.1体现:一旦子类A继承父类B之后,子类A中就获取了父类B中声明的所有的的属性和方法 特别的,父类中声明为Private的属性或方法,子类继承父类以后,仍然认为获取了父类中私有的结构,只有因为 封装性的影响,使得子类不能直接调用父类的结构而已 2.2 子类继承父类以后,还可以声明自己特有的属性或方法,实现功能的拓展。 子类和父类的关系,不同于子集和结合的关系,子类可以去拓展,比父类更丰富。 extends:延申,拓展 三、Java中关于继承性的规定: 1.一个类可以被多个子类继承 2.Java中类的单继承性:一个类只能有一个父类 3.字符类时相对的概念 4.子类直接继承的父类叫直接父类,间接继承的叫间接父类 5.子类继承父类以后,就获取了父类以及所有间接父类中声明的属性和方法 四、 1.如果我们没有显示的声明一个类的父类的话,则此类继承于java.lang.Object类 2.所有的java类(除java.lang.Object类之外)都直接或间接的继承于java.lang.Object类 3.意味着,所有的java类具有java.lang.Object类声明的功能
父类:
public class Creature {
public void breath(){
System.out.println("呼吸");
}
}
子类:
public class Person extends Creature{
String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
private int age;
public Person(){
}
public Person(String name,int age){
this.name=name;
this.age=age;
}
public void eat(){
System.out.println("吃饭");
sleep();
}
private void sleep(){
System.out.println("睡觉");
}
}
主类:
public class ExtendsTest {
public static void main(String[] args) {
Person p1 = new Person();
//p1.age=1;
p1.eat();
Student s1 = new Student();
//s1.age=2;
s1.setAge(10);
System.out.println(s1.getAge());
s1.eat();
s1.name="洪猪雯";
System.out.println(s1.name);
System.out.println("===========================");
//s1.sleep();
s1.eat();
s1.breath();
Creature c1 = new Creature();
}
}
十、重写
方法的重写(override/overwrite) 1.重写:子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖操作 2.应用:重写以后,当创建子类对象以后,通过子类对象调用子父类中的同名同参数的方法时,实际执行的是子类重写父类的方法。 3.重写的规定: 方法的声明:权限修饰符 返回值类型 方法名(形参列表) throws 异常类型{ //方法体 } 约定俗称:子类中的叫重写的方法,父类中的叫被重写的方法 1.子类重写的方法名和形参列表和父类被重写的方法的方法名和形参列表相同 2.子列重写的方法的权限修饰符不小于父类被重写的方法的权限修饰符 ==》特殊情况:子类不能重写父类中声明为private权限的方法 3.返回值类型: 》父类被重写的方法值是void,子类也必须是void 》父类被重写的方法值是A类型,则子类重写的方法的返回值类型可以是A类或A类的子类 》父类被重写的方法值是基本数据类型(比如:double),则子类重写的方法的返回值类型必须是相同的基本数据类型(必须也是double类型) 4.子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型(具体异常处理说明) ======================================================================================= 子类和父类的同名同参数的方法要么都声明为非static的(考虑重写),要么都声明为static的(不是重写)。 面试题:区分方法的重载与重写? ①从二者的概念方面 ②从二者的注意规则 ③从多态性:重载不表现为多态性,重写表现为多态性。 重载:是指同一个类中的多个方法具有相同的名字,但这些方法具有不同的参数列表,即参数的数量或参数类型不能完全相同 重写:是存在子父类之间的,子类定义的方法与父类中的方法具有相同的方法名字,相同的参数表和相同的返回类型
十一、super关键字的使用
1.super理解为:父类的 2.super可以用来调用:属性、方法、构造器 3.super的使用,调用属性和方法: 3.1.我们可以在子类的方法或构造器中,通过使用"super.属性"或”super.方法“的方式,显示的调用父类中声明的属性或方法。但是 ,通常情况下,我们习惯省略super。 3.2.特殊情况,当子类和父类都具有相同的属性时,我们要想在子类中调用父类的属性,则必须使用super.属性的方式,表明调用的时父类中声明的属性 3.3.当子类重写了父类的方法以后,我们想在子类的方法中调用父类中被重写的方法时,则必须使用super.方法的方式,表明调用的时父类中声明的属性 4.super的使用,调用构造器: 4.1.我们可以在子类的构造器中显示的使用“super(形参列表)”的方式,调用父类中申明的指定的构造器 4.2.super(形参列表)的使用,必须声明在子类构造器的首行 4.3.我们在类的构造器中,针对于this(形参列表)或super(形参列表)只能二选一,不能同时出现 4.4.当我们在构造器首行没有显示的声明,则默认调的叫super(); 4.5.在类的多个构造器中,至少有一个类的构造器中使用了super(形参列表),调用父类中的构造器 this(形参列表):本类重载的其他的构造器 super(形参列表):调用父类中指定的构造器 this和super的可区分方法: super:它引用父类中的成员 super.成员函数据名(实参) this:它代表当前对象名 super()和this()类似,区别是,super()在子类中调用父类的构造方法,this()在本类内调用本类的其它构造方法。 super()和this()均需放在构造方法内第一行。 尽管可以用this调用一个构造器,但却不能调用两个。 this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在, 所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。 this()和super()都指的是调用构造方法,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块
十二、面向对象特征三:多态性
1.理解多态性:一个事物的多种形态 2.何为多态性: 对象的多态性:父类的引用指向子类的对象,(或子类的对象赋给父类的引用) 3.多态的使用:虚拟方法调用 有了对象的多态性之后,我们在编译期,只能调用父类中声明的方法,但是运行期,我们实际执行的是子类中重写父类的方法 总结:(只用于方法)编译看左边,运行看右边 4.多态性的使用前提: 1.要有类的继承关系。 2.要有方法的重写 5.对象的多态性,只适用于方法,不适用于属性。此时编译和运行都看左边 p2.earnMoney();不能调用子类所特有的方法。有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的,但是由于变量声明为父类类型,导致 编译时,只能调用父类中声明的属性和方法。子类特有的属性和方法不能调用。 如何才能调用子类特有的属性和方法: 1.强制类型转化:Man m1 = (Man)p2; 使用强化时可能会出现异常 2.a instanceof A:判断对象a是否是类A的实例,如果是,返回true,不是,返回false 如果返回true,则A的父类放进去也会是true 面试题:多态是编译时行为还是运行时行为? 是运行时行为。随机生成3个数字,然后用switch(key)方法,当0是创建猫的对象,1是创建狗的对象,3是创建羊的对象。在随机数不确定时,不能 知道我们要创建的是哪个对象,只有运行出来才知道。 面试题: ==和equals()区别? (1)==如果比较的是基本数据类型,那么比较的是变量的值 如果比较的是引用数据类型,那么比较的是地址值(两个对象是否指向同一块内存) (2)equals如果没重写equals方法比较的是两个对象的地址值 如果重写了equals方法后我们往往比较的是对象中的属性的内容 equals()方法最初在Object类中定义的,默认的实现就是使用== 一、==:运算符 1.可以说使用在基本数据类型变量和应用数据类型变量中 2.如果比较的是基本数据类型变量:比较两个变量保存的数据是否相等(不一定类型相同) 如果比较的是引用数据类型变量:比较两个对象的地址值是否相等 二、equals()方法的使用 1.是一个方法,而非运算符 2.只适用于引用数据类型 3.Object类中equals()的定义: public boolean equals(Object obj){ return (this == obj) } 说明:Object类中定义的equals()和==的作用是相同的,比较两个对象的地址值 4.像String,Data,File,包装类等都重写了Object类中的equals()方法,重写以后,比较哦啊的不是两个引用的地址是否相同,而是比较两个对象的 “实体内容”是否相同 5.通常情况下,我们自定义的类如果使用equals()的话,也通常是比较的是两个对象的“实体内容”是否相同,那么就需要对Object类中equals()进行重写 重写的原则:比较两个对象的实体内容是否相同 Object类中toString()的使用 1.当我们输出一个对象的引用时,实践上就是调用当前对象的toString() 2.像String,Data,File,包装类等都重写了Object类中的toString()方法 使得调用对象的toString()时,返回实体内容信息
十三、关键字的使用
static关键字的使用 1.static:静态的 2.static可以用来修饰:属性,方法,代码块,内部类 3.使用static修饰属性:静态变量 3.1属性:按是否使用static修饰,又分为:静态属性 vs 非静态属性(实例变量) 实例变量:我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性。当修改其中一个的非静态属性时,不会导致其他对象中同样属性值得修改 静态变量:我们创建了类的多个对象,对各对象共享同一个静态变量,当通过某一个对象修改静态变量时,对导致其他对象中同样属性值修改 3.2.static修饰属性的其他说明 1.静态变量随着类的加载而加载,可以通过“类.静态变量”的方式进行调用 2.静态变量的加载要早于对象的创建 3.由于类只会加载一次,则静态变量也是会存在一份,存在方法区的静态域中 4. 类变量 实例变量 类: yes no 对象: yes yes 4.使用static修饰方法:静态方法 1.随着类的加载而加载,可以通过“类.静态方法”进行调用 2. 静态方法 非静态方法 类: yes no 对象: yes yes 3.静态方法中,只能调用静态的方法或属性 非静态方法中,既可以调用静态的方法或属性,也可以调用非静态的方法或属性 5.static注意点: 在静态的方法内,不能使用this关键字,super关键字 关于静态属性和静态方法的使用,从生命周期的角度区理解 6.在开发中如何确定一个属性是否要声明为static? >属性是可以被多个对象所共享的,不会随着对象的变化而变 >类中的常的常量常常声明为static 在开发中如何确定一个方法是否要声明为static? >操作静态属性的方法,通常设置为static >工具类中的方法,习惯上声明为static的,比如:Math、Arrays、Collections 单列设计模式: 1.采用一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例。 2.如何实现? 饿汉式 懒汉式 3.区分饿汉式和懒汉式: 饿汉式:坏处==》对象加载时间过长,一上来就创建对象了 好处==》线程安全的 懒汉式:好处==》延迟对象的创建,用的时候才区创建对象 目前写法坏处==》线程不安全------》到多线程内容式在修改 main()方法的使用说明: 1.main()方法作为程序的入口 2.main()方法也是一个普通的静态方法 3.main()方法可以作为我们于控制台交互的方式。之前用的是Scanner 类的成员之四:代码块(或初始化块) :执行由父及子,静态先行 1.代码块的作用:用来初始化类、对象 2.代码块如果有修饰的话,只能使用static 3.分类:静态代码块 vs 非静态代码块 4.静态代码块 》内部可以有输出语句 》随着类的加载而执行,而且只执行一次 》作用:可以初始化类的信息 》如果一个类中定义了多个静态代码块,则按照证明的先后顺序进行加载 》静态代码块的执行要优先于非静态代码块的执行 》静态代码块内只能调用静态的属性、静态的方法,不能调用非静态的结构 5.非静态代码块 》内部可以有输出语句 》随着对象的创建而执行 》每创建一个对象就执行一次非静态代码块 》作用:可以在创建对象时,对对象的属性等进行初始化 》如果一个类中定义了多个非静态代码块,则按照证明的先后顺序进行加载 》非静态代码块内能调用静态的属性、静态的方法,或非静态的属性和方法 对属性可以赋值的位置默: 1.默认初始化 2.显式初始化 3.构造器中赋值 4.通过“对象.方法”或“对象.属性”的方式,赋值 5.在代码块中赋值 以上操作的先后顺序:1-->2/5-->3-->4 这里2和5是同级别,只是看谁先写,看谁后写 final:最终的 1.final可以用来修饰的结构:类、方法、变量 2.final 用来修饰一个类:此类不能被其他类所继承 比如:String类、System类、StringBuffer类 3.final 用来修饰一个方法:此方法不能被重写 比如:Object类中getClass() 4.final 用来修饰变量:此时的”变量“就称为一个常量 4.1 final修饰属性:可以考虑赋值的位置有:显示初始化,代码块中初始化,构造器中初始化 4.2 final修饰局部变量:尤其是用final修饰形参时,表明此形参是一个常量。当我们调用此方法时,给常量形参赋一个实参,一旦赋值以后,就只能在方法 体内使用此形参,但不能在进行重新赋值 static final 用来修饰属性:全局常量 用来修饰方法:通过类来调用,且不能被重写 abstract关键字的使用: 1.abstract:抽象的 2.abstract可以用来修饰的结构:类、方法 3.abstract修饰类:抽象类 》此类就不能实例化 》抽象类中一定有构造器,虽然自己不能使用,但是便于子类实例化时要使用(涉及:子类对象实例化的全过程) 》开发中,都会提供抽象类的子类,让子类对象实例化,完成相关的操作 4.abstract修饰方法:抽象方法 》抽象方法只有方法的声明,没有方法体 》包含抽象方法的类,一定是一个抽象类。反之,抽象类中是可以没有抽象方法的 》若子类重写了父类中的所有的抽线方法,此子类方可实例化 若子类没有重写父类中的所有的抽象方法,则此子类也是一个抽象类,需要使用abstract来修饰 5.abstract使用上的注意点: 1.abstract不能用来修饰:属性,构造器等结构 2.abstract不能用来修饰私有方法、静态方法、final的方法。 私有方法是不能被重写的。声明为static认为不是重写,所以也不能使用。final的类是不能被继承的。 interface接口的使用: 1.接口使用interface来定义 2.在Java中,接口和类是并列的两个结构 3.如何定义接口,定义接口中的成员 3.1 JDK7及以前,只能定义全局常量和抽象方法 》全局常量:public static final的,但是书写时,可以省略 》抽象发法:public abstract的 3.2 JDK8,除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法 》接口中定义的静态方法,只能通过接口来调用 》通过实现类的对象,可以调用接口中的默认方法 》如果实现类重写了接口中的默认方法,调用时,仍然使用的是重写以后的方法 》如果子类(或实现类)继承的父类和实现的接口中声明了同名同参数的方法,那么子类在没有重写此方法的情况下,默认调用的是父类中的同名同参数的方法--》类优先原则 》如果实现类实现了多个接口,而多个接口中定义同名同参数的默认方法,那么在实现类没有重写此方法的情况下,报错---》接口冲突,那么必须重写此方法 》如何在子类(或实现类)的方法中调用父类,接口中被重写的方法===》CompareA.super.method3(); 4.接口中不能定义构造器的,意味着接口不可以实例化 5.Java开发中,接口都通过让类去实现(implements)的方式来使用 如果实现类覆盖了接口中的所有抽象方法,则此是实现类就可以实例化 如果实现类没有覆盖接口中所有的抽线方法,则此实现类仍为一个抽象类 6.Java类可以实现多个接口 ---》弥补了Java单继承性的局限性 格式:class AA extends BB implements CC,DD,EE 7.接口和接口之间可以多继承 ============================================== 8.接口的具体使用:体现多态性 接口的使用 1.接口的使用上也满足多态性 2.接口,实际上就是定义了一种规范 3.开发中,体会面向接口编程 9.接口,实际上可以看做是一种规范 面试题:抽象类和接口有哪些异同? 不同点: 1.关键字不同: ① 继承抽象类的关键字是extends,而实现接口的关键字是implements; ②定义抽象类的关键字是abstract class,而定义接口的关键字是interface; 2.权限修饰不同:抽象方法可以有public、protected和default这些修饰符(缺省情况下默认为public),而接口方法只能是public ; 3.抽象类中可以有构造方法,而接口中不能有构造方法;接口中如果写了构造方法,编译报错:Interfaces cannot have constructors 4.抽象类中既可以有抽象方法也可以有普通方法,接口中只能有抽象方法; 5.接口可以被多继承,抽象是单继承 相同点: (1) 都可以被继承 (2) 都不能被实例化 (3) 都可以包含方法声明 (4) 派生类必须实现未实现的方法
内的内部成员之五:内部类 1.Java中允许一个类A声明在另一个类B中,则类A就是内部类,类B就是外部类 2内部类的分类:成员内部类(静态、非静态) VS 局部内部类(方法内,代码块内,构造器内) 3.成员内部类: 一方面:作为外部类的成员: 》调用外部类的结构 》可以被static修饰 》可以被四种不同的权限修饰符修饰 另一方面:作为一个类: 》类内可以定义属性、方法、构造器 》可以final修饰,表示此类不能被继承。言外之意,不使用final可以被继承 》可以abstract修饰 4.关注如下的3个问题; 4.1如何实例化成员内部类的对象 //创建Dog实例(静态成员内部类) Person.Dog dog = new Person.Dog(); dog.show(); //创建Bird实例(非静态的成员内部类) Person p = new Person(); Person.Bird bird =p.new Bird(); bird.sing(); 4.2如何在成员内部类中区分调用外部类的结构 System.out.println(name);//方法的形参 System.out.println(this.name);//内部类的属性 System.out.println(Person.this.name);//外部类的属性 4.3 开发中局部内部类的使用==》看《Inner Class Test.java》