static关键字:
1.static可以修饰:
1).成员变量:存在静态存储区。被所有对象共享;
2).成员方法:存在静态存储区。被所有对象共享;
2.static关键字的特点:
1.随着类的加载而加载;
2.优先于对象而存在;
3.被所有类的对象共享;
4.可以通过"类名"调用,也可以通过"对象名"调用;
static关键字的注意事项:
1.在static的方法中,不能使用this关键字;(因为此时还没有对象空间产生)
2.静态方法,只能访问静态成员(静态成员变量和静态成员方法)
----------------------------------------------------------------------------------------
1.继承:
*继承的好处:
1.提高了代码的复用性;
2.提高了代码的可维护性;由于共性的内容被抽取到一个类中,如果放生更改,只需改父类一处即可;
*继承的弊端:
1.一旦两个类具有了"子父关系",也就意味着有了"依赖关系"。子类依赖于父类。
*Java中继承的特点:
1.Java只允许单继承:一个类只能继承自一个类;一个儿子只能有一个爹;
2.Java允许多级继承:Z继承自Y,Y继承自X;Z就拥有了Y 和X中允许被继承的成员;
*继承的注意事项:
1.子类只能继承父类所有非私有的成员(成员方法和成员变量):
2.子类不能继承父类的构造方法,但是可以通过super(后面讲)关键字去访问父类构造方法。
3.不要为了部分功能而去继承;
*什么时候使用继承:
当"子类"相对于"父类"为"is a(是一个)"的关系时,可以使用继承:
我们说:Student是一个Person,就可以继承自Person
继承中成员变量的关系:
在子类方法中访问一个变量
首先在子类局部范围找
然后在子类成员范围找
最后在父类成员范围找(肯定不能访问到父类局部范围)
如果还是没有就报错。
class Fu
{
int num = 10000;
}
class Zi extends Fu
{
int num = 100;//子类的成员变量,覆盖了父类中同名的成员变量
//在Zi类内部访问num
void show(){
int num = 10;
System.out.println("num = " + num);//10:就近原则。先找"局部变量"-->"成员变量" --> "父类"
System.out.println("本类的num : " + this.num);//本类的num:先在"本类"找,如果没有,会去"父类"找
System.out.println("访问父类的num :" + super.num);//访问父类的num
}
}
*继承中构造方法的关系:
1.当实例化一个子类对象时,会同时实例化一个父类对象;
*super和this关键字:
1.super:
1).在子类中使用;
2).存储的是"父类的引用";它指向父类对象空间;
3).在子类中,使用super可以访问父类的:成员变量、成员方法、构造方法.
在子类中调用父类成员:
成员变量:
class Fu{
int num = 10;
}
class Zi extends Fu{
void show(){
System.out.println(super.num);
}
}
成员方法:
class Fu{
void fun1(){
System.out.println("Fu-->fun1()");
}
}
calss Zi extends Fu{
void show(){
super.fun1();//调用父类的成员方法;
}
}
调用父类的构造方法:
class Fu{
}
class Zi extends Fu{
Zi(){
super();//调用父类无参的构造方法;
System.out.println("Zi的构造方法");
}
}
4).有一种情况,子类必须显示的使用super()调用父类的构造方法:
当父类没有"无参构造方法"时;
1.当实例化子类对象时,Java会去实例化它的父类-->默认调用父类"无参构造方法";如果父类没有"无参构造方法",那么Java 就没有办法调用;这时,子类必须显示的使用super(),告诉Java编译器,调用哪个带参的构造方法,并传递什么样的参数;
5).当使用super调用父类的构造方法时,必须写在这个构造方法的:第一句有效代码;
*this:
1).任何类中都可以使用;
2).存储的"本类对象的引用";它指向的本类对象的空间;
3).this可以访问本类对象的:成员变量、成员方法、构造方法
this访问本类成员:
成员变量:
class Student{
String name;
void show(){
System.out.println(this.name);
}
}
成员方法:
class Student{
void f1(){
}
void f2(){
this.f1();//调用本类的方法
}
}
构造方法
class Student{
Student(){
System.out.println("无参的构造方法");
}
Student(int n){
// Student();//掉用本类其它构造方法。不可以这样调用。
this();//调用本类无参的构造方法;
System.out.println("带参的构造方法");
}
}
4).调用本类其它构造方法使用this()。可以带参数。
注意:this()语句,必须是这个构造方法的第一条有效语句;
注意:super()和this()语句不能同时存在;
*方法的重写:
1.子类中出现了和父类中一模一样的方法声明,也被称为方法覆盖,方法重写(复写);
2.重写的格式:
1).返回值类型 方法名 ,形参列表:必须完全一致;
A."返回值类型"和"方法名"相同,"参数列表"不同:编译通过。类似于"重载"
B."方法名"和"参数列表"相同,"返回值类型"不同:编译错误。如果"方法名"和"形参列表"相同,要求"返回值类型"必须相同;
2).访问修饰符:
要求:
子类的方法所具有的访问修饰符必须跟父类的方法的访问修饰符相同,或更宽的访问修饰符;
public,protected,(默认),private(从宽到窄)
*方法重写的注意事项
1.父类中私有方法不能被重写。
2.子类重写父类方法时,访问权限不能更低。必须是具有:相同,或更宽的访问权限;
3.父类静态方法,子类也必须通过静态方法进行重写。
(其实这个算不上方法重写,但是现象确实如此,至于为什么算不上方法重写,多态中我会讲解)
/*重写和重载,this和super面试题
1.方法重写和方法重载的区别?方法重载能改变返回值类型吗?
1.Overload:重载
2.Override:重写
1.重载:在一个类中,可以定义多个同名的方法,但形参列表不完全相同;跟返回值无关;
2.重写:在子类中,可以定义跟父类一模一样的方法(返回值类型、方法名、形参列表完全相同),这时
子类的方法会覆盖父类中同名的方法。
2.this关键字和super关键字分别代表什么?以及他们各自的使用场景和作用。
1.this:
1).在任何类中使用;
2).存储的是本类对象的引用;
3).可以访问本对象的成员变量、成员方法、构造方法;
2.super:
1).在子类中使用;
2).存储的是父类对象的引用;
3).可以访问父类对象的成员变量、成员方法、构造方法;
*/
*final关键字:
1.可以修饰:
1).成员变量:此变量拥有最终的值。是一个"常量"。其值是不能被修改的。或者只能被赋值一次;(也分为基本类型和引用类型)
2).成员方法:表示最终的方法。不能被"重写"。
3).类:表示最终的类;不能被"继承".
4).局部变量:
A.普通局部变量:
A-1:修饰基本数据类型:其值不能被更改;
A-2:修饰引用数据类型:其地址不能被更改;
B.方法的形参:
B-1:修饰基本数据类型:其形参的值不能被更改;
B-2:修饰引用数据类型:其形参的地址不能被更改
*多态的概念:
1.之前我们定义子类,继承自父类。
在使用时:
子类 zl = new 子类();
2.使用多态:可以定义一个"父类类型的引用",指向它的"子类的对象",这种形式就叫:多态
父类 fl = new 子类();
Animal a1 = new Cat();
多态的前提和体现;
1.一定要存在"继承关系";(必须)
2.方法重写;(非必须,但不重写毫无意义)
3.有父类引用指向子类对象;(必须)
*成员变量的访问特点:
1.成员变量:编译看左边(父类中一定要有,否则编译错误);运行看左边(如果子类覆盖父类的成员变量,打印的是父类的)
2.成员方法:编译看左边(父类中一定要有,否则编译错误);运行时看右边(如果子类重写父类的成员方法,调用的是子类的)
3.静态方法:编译看左边(父类中一定要有,否则编译错误);运行时看左边(如果子类重写父类中的静态方法,调用的是父类的)
总而言之:
1.当多态时,访问的成员(成员变量、成员方法)父类中必须要有,否则编译错误。
运行时,只有"被覆盖的普通成员方法"访问的是"子类的",其它都是"父类"的。
*多态的好处和弊端
多态的好处
提高了程序的维护性(由继承保证)
提高了程序的扩展性(由多态保证)
多态的弊端
不能访问子类特有功能
那么我们如何才能访问子类的特有功能呢?
多态中的转型
*多态中的转型
向上转型(隐式的,自动的):
一个"父类"类型的变量,存储"子类对象"的引用;
Fu f = new Zi();//向上转型;
向下转型(显示的,强制转换):
如果我们确定一个"父类"类型的变量,存储了某个具体的"子类对象"的引用。
我们可以将这个"父类类型"强制转换为它所存储的"子类类型";
Zi z = (Zi)f;
*抽象类
抽象类特点:
抽象类和抽象方法必须用abstract关键字修饰
格式:
abstract class 类名 {}
public abstract void eat();
抽象类不一定有抽象方法,有抽象方法的类一定是抽象类
抽象类不能实例化
那么,抽象类如何实例化呢?
按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
抽象类的子类
要么是抽象类
要么重写抽象类中的所有抽象方法
*抽象类的成员特点
成员变量
可以是变量
也可以是常量
构造方法
有构造方法,但是不能实例化
那么,构造方法的作用是什么呢?
用于子类访问父类数据的初始化
成员方法
可以有抽象方法 限定子类必须完成某些动作
也可以有非抽象方法 提高代码复用性
*abstract不能和哪些关键字共存:
1.private:因为一个抽象方法就是被子类重写的。要重写就必须不能为private的。
2.final:因为一个抽象方法就是被子类重写的。而final表示:最终方法,不能被重写。所以这两个关键字冲突;
作用在"类"上也是一样:一个抽象类就是用来被继承的。而final类:表示最终类,不能被继承。所以也是冲突;
3.static:因为一个抽象方法没有方法体。所以不能定义为static的。因为无法被分配空间;
*接口
如果一个抽象类中,没有成员变量,没有实现的方法,只包含了一些"抽象方法",这时,我们可以将这个类定义为"接口":
接口特点:
接口用关键字interface表示
格式:interface 接口名 {}
类实现接口用implements表示
格式:class 类名 implements 接口名 {}
接口不能实例化
那么,接口如何实例化呢?
按照多态的方式,由具体的子类实例化。其实这也是多态的一种,接口多态。
接口的子类
要么是抽象类
要么重写接口中的所有抽象方法(重写接口中的抽象方法时,必须要使用:public访问修饰符;)
*接口的成员特点:
成员变量:
只能是常量
默认修饰符 public static final
构造方法
没有,因为接口主要是扩展功能的,而没有具体存在
成员方法
只能是抽象方法
默认修饰符 public abstract
--------------------------------------------------------------------------
*类与类,类与接口以及接口与接口的关系:
类与类:
继承关系,只能单继承,但是可以多层继承
类与接口:
实现关系,可以单实现,也可以多实现。还可以在继承一个类的同时实现多个接口
接口与接口:
继承关系,可以单继承,也可以多继承
*抽象类和接口的区别
成员区别
抽象类:成员变量、常量、构造方法、实现的方法、抽象方法;
接口:常量、抽象方法;
关系区别
类与类 继承,单继承
类与接口 实现,单实现,多实现
接口与接口 继承,单继承,多继承
设计理念区别
抽象类 被继承体现的是:”is a”的关系。共性功能
接口 被实现体现的是:”like a”的关系。扩展功能
---------------------------------------------------------------------------
*类和类之间的关系:
1."is a"(是一个):常见的就是"继承";
2."has a"(有一个):
3."组成关系":一个类中没有"自有成员",全部都是其它的"类类型",由其它"类"组成的;
class CPU{}
class 硬盘{}
class 主板{}
.....
//"电脑"类全部都是由其它"类"组成
class 电脑{
CPU cpu;
硬盘 yp;
主板 zb;
....
}
4."依赖关系(关联关系)":
class 学生{}
class 老师{}
class 校长{
void talk(学生 xs){//由于talk方法接收的是"学生"类型的对象,我们说:"校长类"依赖于"学生类"
}
void talk(老师 ls){
}
}
|
|