本文为 Week4 笔记
Java程序设计 唐大仕
类
- 组成Java程序的基本要素
- 是一类对象的原型
- 封装类一类对象的状态和方法
字段和方法
- 字段(field)是类的属性,是用变量来表示的。字段又称为域、属性、成员变量
- 方法(method)是类的功能和操作,是用函数来表示的
构造方法
- 构造方法是一种特殊的方法
- 用来初始化(new)该类的一个新的对象
- 构造方法和类名同名,而且不写返回值类型
默认构造方法
- 一般情况下,类都有一个至多个构造方法
- 如果没有定义任何构造方法,系统会自动产生一个构造方法,称为默认构造方法(default constructor)
- 默认构造方法不带参数,并且方法体为空
方法重载(overload)
- 方法的重载(overloading):多个方法有相同的名字,编译 时能识别出来
- 这些方法的 签名 不同(signature),或者是参数个数不同,或者是参数类型不同
- 通过方法的重载可以实现多态(polymorphism)
- 重载的作用 是允许方法的使用者采用不同的参数来调用相同名称的方法
- 方法类型签名 包括方法名称和参数类型两个部分
class MethodOverloadingTest
{
public static void main( String[] argv ){
Person p1 = new Person("Tom", 20);
Person p2 = new Person("Marry", 18);
p1.sayHello();
p1.sayHello(p2);
}
}
class Person
{
String name;
int age;
Person( String name, int age ){
this.name = name;
this.age = age;
}
void sayHello(){
System.out.println("Hello! My name is " + name );
}
void sayHello( Person another ){
System.out.println("Hello, " + another.name + "! My name is " + name );
}
}
this的使用
- 在方法及构造方法中,使用this来访问字段及方法
- 是用this解决局部变量与域变量同名的问题,局部变量(方法中的变量)或参数变量与域名变量同名的问题。
Person( int age, String name )
{
this.age = age;
this.name = name;
}
this.age表示域变量,而age表示的是参数变量
- 在构造方法中,用this调用里一个构造方法,在构造函数中调用另一个构造方法,则这条语句必须放在第一句
class Person {
String name;
int age;
Person( String n, int a ){
name = n;
age = a;
}
Person( String n ){
name = n;
age = 0;
}
Person( int age, String name )
{
this.age = age;
this.name = name;
}
Person( ){
this( 0, "" );
}
boolean isOlderThan( int anAge ){
return this.age > anAge;
}
void sayHello(){
System.out.println("Hello! My name is " + name );
}
void sayHello( Person another ){
System.out.println("Hello," + another.name
+ "! My name is " + name );
}
public static void main(String[] args)
{
Person p = new Person("Li Min", 18);
Person p2 = new Person("Wang Qiang", 20 );
p.sayHello();
p.sayHello(p2);
}
}
继承
- 继承是面型对象程序设计中最重要的特征之一
- 子类(subclass)父类或超类(superclass)
- 父类包括所有直接或间接被继承的类
- Java支持单继承:一个类只能有一个直接父类
继承的好处
子类继承父类的状态和行为
- 可以修改父类的状态或重载父类的行为
- 可以添加新的状态和行为
- 所有的类都是直接或间接继承java.lang.Objectd得到的
好处
- 可以提高程序的抽象程度
- 实现代码重用,提高开发效率和可维护性
字段
- 字段的继承:子类可以继承父类的所有字段
- 字段的隐藏:子类重新定义一个与从父类那里继承来的与变量完全相同的变量,称为域的隐藏
- 字段的添加:在定义子类的时,加上新的域变量,就可以使子类比父类多一些属性
方法
-
方法的继承:父类的非私有方法可以被子类自动继承
-
方法的覆盖(Override)(修改) 子类也可以重新定义与父类同名的方法,实现对父类方法的覆盖(Override)
JDK 1.5 可以使用Override 来标注 -
方法的添加:子类可以添加一些新的方法
-
方法的重载:重载父类的同名方法,重载的方法实际上是新加的方法。
super的使用
- 构造函数是不能继承的,但是子类可以通过super来调用父类的构造方法
- 使用super访问父类的域和方法
- 使用super时 super() 必须放在第一句
public class RoundImageView extends ImageView {
private int mBorderThickness = 0;
private Context mContext;
private int defaultColor = 0xFFFFFFFF;
private int mBorderOutsideColor = 0;
private int mBorderInsideColor = 0;
private int defaultWidth = 0;
private int defaultHeight = 0;
public RoundImageView(Context context) {
super(context);
mContext = context;
}
public RoundImageView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
setCustomAttributes(attrs);
}
public RoundImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
setCustomAttributes(attrs);
}
父类对象与子类对象的转换
- 子类对象可以被视为其父类的一个对象
- 父类对象不能被当作其某一个子类的对象
- 如果一个方法的形式参数定义为父类对象,那么在调用这个方法时,可以使用子类对象作为实际参数
- 如果父类对象引用指向的实际是一个子类对象,那么这个父类对象的引用可以用强制类型转换(casting)成子类对象的引用
包
- 包的作用:解决名字空间、名字冲突
- 包的含义:a.名字空间、存储路径(文件夹)b.可访问性(同一包下的各个类默认是可以相互访问的)
- 包层次的根目录是由环境变量CLASSPATH来确定的
- 简单情况下,没有package语句,这时称为无名包(unnamend package)
import语句
-
java编译器自动导入包java.lang.*
-
注意:使用 * 只能表示本层的所有类,不包括子层下的类
CLASSPATH
- 包层次的根目录是由环境变量CLASSPATH来确定的。
- 方法一: 在java 及javac 命令中,用-classpath(或-cp)选项来指明,如: java -classpath d:\code;d:\code\java\classes
- set classpath= D:\code\Java\learncode\ch04\pk;.
访问控制符
成员的访问控制符
同一个类中 | 同一个包中 | 不同包中的子类 | 不同包中的非子类 | |
---|---|---|---|---|
priavte | Yes | — | ||
默认访问权限(包访问权限) | Yes | Yes | ||
protected | Yes | Yes | Yes | |
public | Yes | Yes | Yes | Yes |
seter和getter
- 属性使用private更好的封装和隐藏,外部类不能随意的存取和修改
- 提供方法来存取对象的属性,在方法中可以对给定的参数的合法性进行校验
- 方法可以用来给出计算后的值
- 方法可以完成其他必要的工作(如清理资源、设定状态,等等)
- 只提供getXX方法,而不提供setXx方法,可以保证属性是只读的
非访问控制符
基本含义 | 修饰符 | 修饰成员 | 修饰的局部变量 | |
---|---|---|---|---|
static | 静态的、非实例的、类的 | 可以修饰内部类 | Yes | |
默认访问权限(包访问权限) | Yes | Yes | ||
final | 最终的、不可改变的 | Yes | Yes | Yes |
abstract | 抽象的、不可实例化的 | Yes | Yes |
static 字段
- 静态字段最本质的特点是:它是类的字段,不属于任何一个对象实例
- 它不保存在某个对象实例的内存区间中,而是保存在类的内存区域的公共存储单元
- 类变量可以通过类名直接访问,以可以通过实例对象来访问,两种方法的结果是相同的
- static在一定意义上,剋来表示全局变量
static 方法
- 用static修饰符修饰的方法仅属于类的静态方法,又称为类方法
- 于此相对,不用static修饰的方法,则为实例方法
- 类方法的本质是该方法是属于整个类,不是属于某个类的实例的
- 声明一个方法为static有以下几重含义
- (1)非static的方法是属于某个对象的方法,在这个对象创建时,对象的方法在内存中拥有自己专用的代码段。
而static方法是属于整个类的,它在内存中的代码段将随着类的定义而进行分配和装载,不被任何一个对象专有 - (2)由于static方法是属于整个类的,所以它不能操纵和处理属于某个对象的的成员变量,而只能处理整个类的
成员变量,即static方法只能处理本类中的static域或调用static方法 - (3)static方法中,不能访问实例变量,不能使用this 或super
- (4)调用这个方法时,应该使用类名直接调用,也可以用某一个具体的对象名
final类
- 如果一个类被定义为final修饰和限定,说明这个类不能被继承,即不可能有子类
final方法
- final修饰符所修饰的方法,而不能被子类所覆盖的方法
final字段及final局部变量
final字段、final局部变量(方法中的变量)
- 它们的值一旦给定就不能修改
- 是只读的,它们能切只能被赋值一次,而不能被赋值多次
一个字段被 static final 两个修饰符所限定时,它可以表示常量 如:Math.PI
关于赋值
- 在定义static final 域时,若不给定初始值,则按默认值进行初始化(数值为 0,boolean 为false ,引用类型为null)
- 在定义final字段时,若不是static的域,则必须只能赋值一次,不能缺省 这种赋值方式有两种:一种是在定义
变量时赋值初始化,二是子啊每一个构造函数中进行赋值 - 在定义为final局部变量时,必须且只能赋值一次。他的值可能不是常量,但它的取值在变量存在期间不会改变
abstract
- 凡是用abstract修饰的类被称为抽象类
- 抽象类不能实例化
抽象类的意义
为其子类提供一个公共的类型 封装子类中得重复内容 定义抽象方法,子类虽然有不同的实现 但是定义是一致的
abstract方法
- 被abstract所修饰的方法叫抽象方法,抽象方法的作用在所有的子类定义一个统一的接口。对象方法只需要声明,而不需要实现,即用分号(;)而不是用{},格式如下:
- abtract retutrnType abstracmethod([]);
- 抽象类可以包含抽象方法,也可以不包含抽象方法。但是,一旦某个类中包含类abstract方法,则这个类必须声明为
抽象类 - 抽象方法在子类中必须被实现,否则子类任然是abstract的
接口:某种特征的约定
- 所有的方法都自动的是 public abstract
- 接口的实现 implements 可以实现多继承,和类的继承关系无关
- 通过接口可以实现不相关类的相同行为,而不需考虑这些类之间的层次关系。从而一定意义上实现了多继承
- 通过接口可以实现多个类需要实现的方法
- 通过接口可以了解对象的交互界面,而不需要了解对象所对应的类
- 通常以able或ible结尾,表明接口能完成一定的行为
- 接口声明中还可以包括对接口的访问权限以及它的父接口列表
[public] interface interfaceName [extends listOfsuperInterface]{
...
}
- 其中public指明任意类可使用这个接口,缺省情况下,只能与该接口点过意在同一个包中的类才可以访问这个接口
- extends 子句与类声明中的 extends子句基本相同,不同的是一个接口可以有多个父接口,用逗号隔开,而一个类只能有一个父类。子接继承父类中所有的常量和方法
- 方法定义的格式为:
- returnType methodName([paramlist])
- 接口中只进行方法的声明,而不提供方法的实现,所以,方法定义没有方法体,且用分号(;)结尾。在接口中声明的方法具体有public和abstract属性,所以定义的时候这两个关键词是可以省略的
- 如果接口中定义了和父类接口同名的常量或相同的方法,则父接口中的常量被隐藏,方法被重载
接口的实现
- 在类中可以使用接口中定义的常量
接口类型
- 接口可以作为一种引用类型来使用。任何实现该接口的类的实例都可以存储在该接口类型的变量中,通过这些变量可以访问类所实现的接口中的方法。Java运行时系统的确定该使用那个类中的方法
- 把接口作为一种数据类型可以不需要了解队形所对应的具体类
接口中的常量
- 接口体中可以包含常量定义
- 常量定义的格式为: type NAME = value;
- 其中type可以是任意类型,NAME 是常量名,通常用大写,value 是常量值
- 在接口中定义的常量可以被实现该接口的多个类共享
- 在接口中定义的常量具有 public,static,final的属性
Java8中的接口
- Java 8 以上,接口成员还可以是:
- static 方法
- 具有实现的方法(default方法) 默认方法的好处:提供一个默认实现,子类在implements 可以不用在重复新写了
接口的意义
规范、扩展、回调
抽象类接口区别
引用于:http://www.jackywang.tech/AndroidInterview-Q-A/chinese/java/%E6%8A%BD%E8%B1%A1%E7%B1%BB%E6%8E%A5%E5%8F%A3%E5%8C%BA%E5%88%AB-360.html
默认的方法实现 抽象类可以有默认的方法实现完全是抽象的。
接口根本不存在方法的实现(在Java8 此句描述不准确)
实现 子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现。
子类使用关键字implements来实现接口。它需要提供接口中所有声明的方法的实现
构造器
抽象类可以有构造器
接口不能有构造器
与正常Java类的区别
除了你不能实例化抽象类之外,它和普通Java类没有任何区 接口是完全不同的类型
访问修饰符
抽象方法可以有public、protected和default这些修饰符 接口方法默认修饰符是public。你不可以使用其它修饰符。
main方法
抽象方法可以有main方法并且我们可以运行它
接口没有main方法,因此我们不能运行它。
多继承
抽象类在java语言中所表示的是一种继承关系,一个子类只能存在一个父类,但是可以存在多个接口。
速度
它比接口速度要快
接口是稍微有点慢的,因为它需要时间去寻找在类中实现的方法。
添加新方法
如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。
如果你往接口中添加方法,那么你必须改变实现该接口的类。(在Java8 此句描述不准确)
我是IT小王,如果喜欢我的文章,可以扫码关注我