Java面向对象02
一、Java面向对象3
1. 接口和抽象类的区别是什么?
Java提供和支持创建抽象类和接口。它们的实现有共同点,不同点在于:
• 接口中所有的方法隐含的都是抽象的。而抽象类则可以同时包含抽象和非抽象的方法。
• 类可以实现很多个接口,但是只能继承一个抽象类
• 类如果要实现一个接口,它必须要实现接口声明的所有方法。但是,类可以不实现抽象类声明的所有方法,当然,在这种情况下,类也必须得声明成是抽象的。
• 抽象类可以在不提供接口方法实现的情况下实现接口。
• Java接口中声明的变量默认都是final的。抽象类可以包含非final的变量。
• Java接口中的成员函数默认是public的。抽象类的成员函数可以是private,protected或者是public。
• 接口是绝对抽象的,不可以被实例化。抽象类也不可以被实例化,但是,如果它包含main方法的话是可以被调用的。
2. 接口是否可继承接口?抽象类是否可实现(implements)接口?抽象类是否可继承实体类(concrete class)?
接口可以继承接口。抽象类可以实现(implements)接口,抽象类是否可继承实体类,但前提是实体类必须有明确的构造函数。
二、Java面向对象4
1. 形式参数和返回值的问题
(1) 形式参数:
类名:需要该类的对象
抽象类名:需要该类的子类对象
接口名:需要该接口的实现类对象
(2) 返回值类型:
类名:返回的是该类的对象
抽象类名:返回的是该类的子类对象
接口名:返回的是该接口的实现类的对象
(3) 链式编程
对象.方法1().方法2().......方法n();
这种用法:其实在方法1()调用完毕后,应该返回一个对象;
方法2()调用完毕后,应该返回一个对象。
方法n()调用完毕后,可能是对象,也可以不是对象。
2. 包
(1) 其实就是文件夹
(2) 作用:
A:区分同名的类
B:对类进行分类管理
a:按照功能分
b:按照模块分
(3) 包的定义
package 包名;
多级包用.分开。
(4) 注意事项:
A:package语句必须在文件中的第一条有效语句
B:在一个java文件中,只能有一个package
C:如果没有package,默认就是无包名
(5) 带包的编译和运行
A:手动式
B:自动式
javac -d . HelloWorld.java
3. 导包
(1) 我们多次使用一个带包的类,非常的麻烦,这个时候,Java就提供了一个关键字import。
(2) 格式:
import 包名...类名;
另一种:import 包名...*;(不建议)
(3) package,import,class的顺序
package > import > class
4. 权限修饰符
(1) 权限修饰符
| 本类 | 同一个包下 | 不同包下的子类 | 不同包下的无关类 | |
| private | Y | |||
| 默认 | Y | Y | ||
| protected | Y | Y | Y | |
| public | Y | Y | Y | Y |
(2) 这四种权限修饰符在任意时刻只能出现一种。
public class Demo {}
5. 常见的修饰符
(1) 分类:
权限修饰符:private,默认,protected,public
状态修饰符:static,final
抽象修饰符:abstract
(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();
(4) abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized?
都不能
(5) 使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?
使用final关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的。
例如,对于如下语句:final StringBuffer a=new StringBuffer(“immutable”);
执行如下语句将报告编译期错误:a=new StringBuffer("");但是,执行如下语句则可以通过编译:a.append(" broken!");
有人在定义方法的参数时,可能想采用如下形式来阻止方法内部修改传进来的参数对象:public void method(final StringBuffer param) {}
实际上,这是办不到的,在该方法内部仍然可以增加如下代码来修改参数对象:param.append(“a”);
(6) 父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的。
final不能用于修饰构造方法。
6. 内部类
(1) 把类定义在另一个类的内部,该类就被称为内部类。
举例:把类B定义在类A中,类B就被称为内部类。
(2) 内部类的访问规则
A:可以直接访问外部类的成员,包括私有
B:外部类要想访问内部类成员,必须创建对象
(3) 内部类的分类
A:成员内部类
public class A { String s; class B{ } }
其中B就是成员内部类,实例化B需要先实例化A对象(B b = new A().new B();),B会持有A对象的引用,所以鉴于这点,引出java中的内存泄漏问题。
B:局部内部类类
public class A { public C getB(){ class B extends C{ String s = "B"; } return new B(); } } class C{ String s; }
局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。
(4) 成员内部类
A:private 为了数据的安全性
B:static 为了访问的方便性
成员内部类不是静态的:外部类名.内部类名 对象名 = new 外部类名.new 内部类名();
成员内部类是静态的:外部类名.内部类名 对象名 = new 外部类名.内部类名();
(5) 成员内部类的思考题
30,20,10
class Outer { public int num = 10; class Inner { public int num = 20; public viod show() { int num = 30; System.out.println(num); System.out.println(this.num); System.out.println(Outer.this.num); } } }
(6) 局部内部类
A:局部内部类访问局部变量必须加final修饰。
B:为什么呢?
因为局部变量使用完毕就消失,而堆内存的数据并不会立即消失。
所以,堆内存还是用该变量,而改变量已经没有了。为了让该值还存在,就加final修饰。
通过反编译工具我们看到了,加入final后,堆内存直接存储的是值,而不是变量名。
(7) 匿名内部类
A:是局部内部类的简化形式
B:前提
存在一个类或者接口
C:格式:
new 类名或者接口名() {
重写方法;
}
D:本质:
其实是继承该类或者实现接口的子类匿名对象
(8) 匿名内部类在开发中的使用
匿名内部类应该是平时我们编写代码时用得最多的,在编写事件监听的代码时使用匿名内部类不但方便,而且使代码更加容易维护。
我们在开发的时候,会看到抽象类,或者接口作为参数。而这个时候,我们知道实际需要的是一个子类对象。
如果该方法仅仅调用一次,我们就可以使用匿名内部类的格式简化。
view.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { } });
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("好好学习,天天向上"); } }); } }
(9) 匿名内部类的思考题
interface Inter { void show(); } class Outer { //补齐代码 public static Inter method() { return new Inter() { public void show() { System.out.println("HelloWorld"); } }; } } class OuterDemo { public static void main(String[] args) { Outer.method().show(); //"HelloWorld" } }
7. Object类
(1) Object是类层次结构的根类,所有的类都直接或者间接的继承自Object类。
(2) Object类的构造方法有一个,并且是无参构造
这其实就是理解当时我们说过,子类构造方法默认访问父类的构造是无参构造
(3) 要掌握的方法:
A:toString()
返回对象的字符串表示,默认是由类的全路径+'@'+哈希值的十六进制表示。
这个表示其实是没有意义的,一般子类都会重写该方法。
如何重写呢?过程我也讲解过了,基本上就是要求信息简单明了。
但是最终还是自动生成。
B:equals()
比较两个对象是否相同。默认情况下,比较的是地址值是否相同。
而比较地址值是没有意义的,所以,一般子类也会重写该方法。
重写过程,我也详细的讲解和分析了。
但是最终还是自动生成。
(4) 要了解的方法:
A:hashCode() 返回对象的哈希值。不是实际地址值,可以理解为地址值。
B:getClass() 返回对象的字节码文件对象,反射中我们会详细讲解
C:finalize() 用于垃圾回收,在不确定的时间
D:clone() 可以实现对象的克隆,包括成员变量的数据复制,但是它和两个引用指向同一个对象是有区别的。
(5) 两个注意问题;
A:直接输出一个对象名称,其实默认调用了该对象的toString()方法。
B:思考题
== 和 equals() 的区别?
A:==
基本类型:比较的是值是否相同
引用类型:比较的是地址值是否相同
B:equals()
由Object类提供的,可以由子类来进行重写。只能比较引用类型。默认情况下,比较的是地址值是否相同, 这个时候和 “==”是等价的。
但是,我们可以根据自己的需要重写该方法。Java中很多类(String类、Date类、File类等)都对equals方法进行了重写。
。
我们在开发的时候,会看到抽象类,或者接口作为参数。而这个时候,我们知道实际需要的是一个子类对象。

浙公网安备 33010602011771号