封装的步骤:
第一步:属性私有化
第二步:一个属性对外提供两个方法(set,get),外部程序只能通过SET方法修改,GET方法获取,可以在SET方法中设立关卡来保护数据的安全性。
强调:set和get都是实例方法,不可以带static。
不带static的方法称为实例方法,实例方法的调用必须先new对象。
set方法和get方法有严格的格式要求:
set: public void setName(String name){
this.name=name;
}
get:: public String getName(){
retuen name;
}
this和static
1.static
a.所有static修饰的都是类相关的,类级别的。
b.所有static修饰的,都是采用“类名.”的方式访问的。
c.static修饰的变量称为静态变量,修饰的方法称为静态方法。
变量的分类:
变量根据位置划分:
在方法体中声明的变量叫做:局部变量
在方法体外声明的变量叫做:成员变量
成员变量又可以分为:实例变量 静态变量
实例的,都是对象相关的,访问时采用“引用.”的方式访问,需要先new对象
实例相关的,必须先有对象,才能访问,可能会出现空指针异常。
静态的,都是类相关的,访问时采用“类名.”的方式访问。不需要new对象
不需要对象的参与即可访问,没有空指针异常的发生。
什么时候变量声明为实例,什么时候静态呢?
当一个类的所有对象的某个“属性值”不会随着对象的改
变而变化的时候,建议将该属性定义为静态属性(或者说把这个变量定义为静态变量)
静态方法: 当方法体中需要直接访问当前对象的实例变量或者实例方法的时候,该方法必须定义为实例方法,因为只有实例方法中才有 this,静态方法中不存在 this。
//实例方法
不同的客户购物,最终的效果都不同,另外在 shopping()方法中访问了
当前对象的实例变量 name,以及调用了实例方法 pay(),所以 shopping()方法不能定义为静态
方法,必须声明为实例方法
public class Customer {
String name;
public Customer(String name){
this.name = name;
}
public void shopping(){
//直接访问当前对象的 name
System.out.println(name + "正在选购商品! ");
//继续让当前对象去支付
pay();
}
public void pay(){
System.out.println(name + "正在支付! ");
}
}
public class CustomerTest {
public static void main(String[] args) {
Customer jack = new Customer(“jack”);
jack.shopping();
Customer rose = new Customer(“rose”);
rose.shopping();
}
}
/*
工具类”当中的方法一般定义为静态方法,因为工具类就是为
了方便大家的使用,将方法定义为静态方法,比较方便调用,不需要创建对象,直接使用类名
就可以访问。请看以下工具类,为了简化“System.out.println();”代码而编写的工具类
*/
public class U {
public static void p(int data){
System.out.println(data);
}
public static void p(long data){
System.out.println(data);
}
public static void p(float data){
System.out.println(data);
}
public static void p(double data){
System.out.println(data);
}
public static void p(boolean data){
System.out.println(data);
}
public static void p(char data){
System.out.println(data);
}
public static void p(String data){
System.out.println(data);
}
}
public class HelloWorld {
public static void main(String[] args) {
U.p(“Hello World!”);
U.p(true);
U.p(3.14);
U.p(‘A’);
}
}
总结:所有实例相关的,包括实例变量和实例方法,必须先创建对象,然后通过“引用”
的方式去访问,如果空引用访问实例相关的成员,必然会出现空指针异常。
所有静态相关的,包括静态变量和静态方法,直接使用“类名”去访问。虽然静态相关的成员也能使用“引用”去访问,但这种方式并不被主张。
继承
定义:在不同的类中也可能会有共同的特征和动作,可以把这些共同的特征和动作放在一个类中,让其它类共享。因此可以定义一个通用类,然后将其扩展为其它多个特定类,这些特定类继承通用类中的特征和动作。继承是 Java 中实现软件重用的重要手段,避免重复,易于维护。
作用:继承可以解决代码臃肿的问题。换句话说,继承解决了代码复用的问题(代码复用就是代码的重复利用) ,这是继承机制最基本的作用。 继承之后才会衍生出方法的覆盖和多态机制。
特性: ① B类继承 A类,则称 A类为超类(superclass)、父类、基类, B类则称为子类(subclass)、派生类、扩展类。
② java 中的继承只支持单继承,不支持多继承, C++中支持多继承,这也是 java 体
现简单性的一点,换句话说, java 中不允许这样写代码: class B extends A,C{ }。
③ 虽然 java 中不支持多继承,但有的时候会产生间接继承的效果,例如: class C
extends B, class B extends A,也就是说, C 直接继承 B,其实 C 还间接继承 A。
④ java 中规定,子类继承父类,除构造方法和被 private 修饰的数据不能继承外,剩
下都可以继承。
⑤ java 中的类没有显示的继承任何类,则默认继承 Object 类, Object 类是 java 语言
提供的根类(老祖宗类),也就是说,一个对象与生俱来就有 Object 类型中所有的特征。
⑥ 继承也存在一些缺点,例如: CreditAccount 类继承 Account 类会导致它们之间的
耦合度非常高, Account 类发生改变之后会马上影响到 CreditAccount 类。
方法覆盖:
定义:父类中继承过来的方法已经不够用了,子类有必要将这个方法重新再写一遍,所以方法覆盖又被称为方法重写。当该方法被重写之后,子类对象一定会调用重写之后的方法 。
必要条件:① 方法覆盖发生在具有继承关系的父子类之间,这是首要条件;
② 覆盖之后的方法与原方法具有相同的返回值类型、相同的方法名、相同的形式参数列表;
注意事项: ① 由于覆盖之后的方法与原方法一模一样,建议在开发的时候采用复制粘贴的方式,不建议手写,因为手写的时候非常容易出错,比如在 Object 类当中有 toString()方法,该方法中的 S 是大写的,在手写的时候很容易写成小写 tostring(),这个时候你会认为 toString()方法已经被覆盖了,但由于方法名不一致,导致最终没有覆盖,这样就尴尬了;
② 私有的方法不能被继承,所以不能被覆盖;
③ 构造方法不能被继承,所以也不能被覆盖;
④ 覆盖之后的方法不能比原方法拥有更低的访问权限,可以更高(学习了访问控制
权限修饰符之后你就明白了);
⑤ 覆盖之后的方法不能比原方法抛出更多的异常,可以相同或更少(学习了异常之
后就明白了);
⑥ 方法覆盖只是和方法有关,和属性无关;
⑦ 静态方法不存在覆盖(不是静态方法不能覆盖,是静态方法覆盖意义不大,学习
了多态机制之后就明白了);
多态
定义:它的前提是封装形成独立体,独立体之间存在继承关系,从而产生多态机制。多态是同一个行为具有多个不同表现形式或形态的能力。
多态就是“同一个行为”发生在“不同的对象上”会产生不同的效果。
小知识点:
java 中允许这样的两种语法出现,一种是向上转型( Upcasting),一种是向下转型(Downcasting),向上转型是指子类型转换为父类型,又被称为自动类型转换,向下转型是指父类型转换为子类型,又被称为强制类型转换。
无论是向上转型还是向下转型,两种类型之间必须要有 继承关系,没有继承关系情况下进行向上转型或向下转型的时候编译器都会报错。
eg: Animal a = new Cat();
a.catchMouse(); 此代码会编译错误,因为“Animal a = newCat();”在编译的时候,编译器只知道 a 变量的数据类型是 Animal,也就是说它只会去Animal.class 字节码中查找 catchMouse()方法,结果没找到,自然“静态绑定”就失败了,编译没有通过。就像以上描述的错误信息一样:在类型为 Animal 的变量 a 中找不到方法catchMouse()。
//向上转型(子类型转换为父类型)
Animal a = new Cat();
//向下转型:为了调用子类对象特有的方法(父类型转换为子类型)
Cat c = (Cat)a;
c.catchMouse()
代码修改后, 就可以正常运行。直接使用 a 引用是无法调用 catchMouse()方法的,因为这个方法属于子类 Cat中特有的行为,不是所有 Animal 动物都可以抓老鼠的,要想让它去抓老鼠,就必须做向下转型(Downcasting),也就是使用强制类型转换将 Animal 类型的 a 引用转换成 Cat 类型的引用c(Cat c = (Cat)a;),使用 Cat 类型的 c 引用调用 catchMouse()方法。
instanceof 运算符 (在进行任何向下转型的操作之前,要使用 instanceof 进行判断):
instanceof 运算符的运算结果是布尔类型,可能是 true,也可能是 false,假设(c instanceof Cat)结果是 true 则表示在运行阶段 c 引用指向的对象是 Cat 类型,如果结果是 false 则表示在运行阶段 c 引用指向的对象不是 Cat 类型。
Animal a = new Bird();
if(a instanceof Cat){
Cat c = (Cat)a;
c.catchMouse();
多态的三个必要条件:① 继承
② 方法覆盖
③ 父类型引用指向子类型对象
★:方法覆盖主要是说实例方法,静态方法不谈方法覆盖。
super
super 和 this 都可以使用在实例方法当中。
super 不能使用在静态方法当中,因为 super 代表了当前对象上的父类型特征,
静态方法中没有 this,肯定也是不能使用 super 的。
super 也有这种用法:“super(实际参数列表);”,这种用法是通过当前的构造
方法调用父类的构造方法。
“super(实际参数列表);”语法表示调用父类的构造方法,代码复用性增强了,
super()的作用主要是:
第一,调用父类的构造方法,使用这个构造方法来给当前子类对象初始化父类型特征;
第二,代码复用。
super()什么时候不能省略:
当父类中有该实例变量,子类中又重新定义了同名的实例变量,如果想在子类中访问父类的实例变量, super 不能省略。
父类和子类中有同名实例变量或者有同名的实例方法,想在子类中访问父类中的实例变量或实例方法,则super 是不能省略的,其它情况都可以省略。