目录
继承extends
extends关键字
一个类只能有一个父类,一个父类可多个子类 多态
类型定义的时候,可以抽取出其中的公共属性和公共方法定义在父类中,然后定义子类;
子类继承这个父类定义的属性和方法,子类中只需要写自己独有的属性和方法;
public class Shape {
int x;
int y;
void print(){
System.out.println("("+x+","+y+")");
}
public double grith(){
return 0;
}
}
class Rect extends Demo2Shape{
double width;
double height;
public double grith(){
return 2*(width+height);
}
public double area(){
return width*height;
}
}
class Circle extends Demo2Shape{
double r;
public double grith(){
return Math.PI*r*2;
}
public double area(){
return Math.PI*Math.pow(r,2);
}
}
向上造型
创建子类数据类型的对象赋值给父类数据类型的引用变量
Shape s=new Shape();
Shape shape=new Rect();
Shape s1=new Circle();
可直接调用与父类有关的成员变量与方法[重写的也可]
但不能直接调用子类特有的成员变量与方法
shape.x=3;
shape.y=6;
shape.grith();
shape.print();
//shape.width=4; //编译错误
//shape.area() //编译错误
//shape是一个父类的引用变量,且父类中无width成员变量、area()成员方法等
即使创建了一个子类对象但由于赋值到一个父类的引用变量中,则无法访问子类中特有的成员变量与方法
编译错误
编译时,以=号左边的类型为准
此时类型为父类,无法调用子类的特有的成员变量与方法
shape.width=4; //编译错误
编译错误: 编译时,以=号左边的类型为准,此时类型Shape
Shape中无width,也无法引用子类中特有的成员变量与方法
向上造型之后,只能通过引用访问到引用变量对应的类型属性与方法
以强制转换解决该问题
强制转换
将向上造型的变量赋值给一个子类数据类型的变量进行强制转换[必须与向上造型变量中引用的对象类型一致]
//Shape父类 Rect子类
Rect r1=(Rect) shape; //强制转换
r1.width=4;
r1.height=5;
System.out.println("周长:"+r1.grith());
System.out.println("面积:"+r1.area());
将Demo2Shape s1=new Circle(); 强制为矩形
Demo2Rect r2=(Demo2Rect) s
存在 java.lang.ClassCastException类型转化异常
被强制转换的引用,必须是能转换为某种类型的,才能使用强转规则,否则排抛异常
将向上造型的变量赋值给一个子类数据类型的变量进行强制转换[必须与向上造型变量中引用的对象类型一致]
因此在强制转换类型前,先进行类型判断
判断是否为同种类型,再强转
方法一 引用变量.getClass() == 类型.class进行比较
//getClass() 获取引用类型变量所指向的对象的类名
System.out.println(s1.getClass());//class day2.Circle
//类名.class 可获取类型名
System.out.println(Circle.class);//class day2.Circle
//方法一:getClass()类名.class 与向判断是否为同种类型,再强转
if(s1.getClass()==Rect.class){
Rect r2=(Rect) s1;
}
else{
System.out.println("类型不同,无法转换");
}
方法二 变量 instanceof 类型 进行比较
Shape s=new Shape();
Rect r=new Rect();
if(r instanceof Rect)
System.out.println("r指向的对象是Rect类型");
if(s instanceof Rect)
System.out.println("s指向的对象是Rect类型");
//两种方法判断一致
if(r.getClass()==Rect.class)
System.out.println("r指向的对象是Rect类型");
super关键字与函数
子类中可以使用super关键字,调用父类的属性和方法
子类的构造方法中必须通过super函数调用父类的构造方法
调用super()函数,必须写在构造方法的第一行,否则编译错误
当子类自定义构造方法时,必须先使用super调用父类构造
若子类构造没有直接使用super调用父类构造方法,此时要求父类必须有无参构造方法[系统默认调用super()无参构造]
class Father{
int x;
int y;
public Father(){
System.out.println("Father----无参");
}
public Father(int x,int y){
this.x=x;
this.y=y;
}
public void sayHi(){
System.out.println("hello");
}
}
class Son extends Father{
int m;
int n;
public Son(){
// super(); super()函数 表示调用父类的无参构造函数
super(3,6); //super(int,int)函数 表示调用父类的有参构造函数
// super(3,6);调用super()函数,必须写在方法体的第一行,否则编译错误
}
public void print(){
int k=super.x;//调用父类属性
int k2=super.y;
int k3=x+y;//super可省略 继承父类的属性,可以直接使用
super.sayHi();
sayHi();//super可省略 继承父类的属性,可以直接使用
}
public void sayHi(){
//调用父类的sayHi方法
super.sayHi();
//没有用super指定调用父类方法
//优先调用自身的方法 若自身没有此方法,再调用父类的
//sayHi();
}
}
在构造方法中,调用super()函数,必须写在构造方法的第一行,否则编译错误
在其他方法体,若想调用父类方法 则 super.方法名() 位置任意
class F{
public void z(){
System.out.println("FFFFF");
}
}
class S extends F{
public S(){
super();
System.out.println("SSSSSS");
//super(); 编译错误
//构造器中,super()函数必须放在第一排
}
public void z(){
System.out.println("+++++++");
super.z(); //super是关键字 调用父类方法 放置位置任意
}
}
重写
子类从父类继承的方法,如果不能满足子类的需要,可以重写父类的方法
方法名和参数列表和父类保持完全一致,方法的实现不同
子类重写父类的方法之后,子类对象优先调用自己的方法
子类重写父类的方法的时候,可以在重写的方法中,使用super关键字调用到父类的方法
子类调用方法,先调用自身;若未找到,再去父类中调用
public class Shape {
int x;
int y;
void print(){
System.out.println("("+x+","+y+")");
}
public double grith(){
return 0;
}
}
class Rect extends Demo2Shape{
double width;
double height;
@Override
public double grith(){ //重写父类
return 2*(width+height);
}
public double area(){
return width*height;
}
}
class Circle extends Demo2Shape{
double r;
@Override
public double grith(){ //重写父类
return Math.PI*r*2;
}
public double area(){
return Math.PI*Math.pow(r,2);
}
}
注解
注解(@+类型名) 对类、方法、属性进行特殊功能的设置
@Override 重写
必须放在方法前,表示该方法必须重写父类的方法
若未重写父类,则存在编译错误
以下会存在编译错误:
错误写法1
@Override
public double grith1(){ //重写父类
return Math.PIr2;
}
错误写法2
@Override
public int grith(){ //重写父类
return Math.PIr2;
}
错误写法3
@Override
public double grith(int a){ //重写父类
return Math.PIr2;
}
访问控制符private、默认、protected、public
private
只能在自身类中被访问与调用[其他情况均不访问]
默认
能在自身类与同一包下的其他类类或子类被访问与调用 [只能是同一包下的类{其他类与子类都可访问}]
protected
能在自身类、同一包的类或子类、不同包的子类中被访问与调用 [不同包的其他类不可访问]
public
能在自身类、同一包的类或子类、不同包的子类或其他类类中被访问与调用[所有情况均能访问]
package day2;
public class Demo6 {
private String name;
String sex;
protected String hobby;//爱好
public String keyWord;//关键字
}
//同包中的不同类可以访问:默认修饰、protected、pu
class TestA{
public static void main(String[] args) {
Demo6 d=new Demo6();
// d.name="啦啦"; //私有变量,只能在自己类中被访问
//同包中的不同类可以访问:默认修饰、protected、public
d.sex="男";
d.hobby="看书";
d.keyWord="自信";
}
}
//同包中的继承类可以访问:默认修饰、protected、pu
class TestB extends Demo6{
void print(){
// System.out.println(name);//私有
//同包中的继承类可以访问:默认修饰、protected、public
System.out.println(sex);
System.out.println(hobby);
System.out.println(keyWord);
}
}
import day2.Demo6;
//不同包中的继承子类 可访问 protected public
public class TestC extends Demo6 {
void print(){
// System.out.println(name);//私有
// System.out.println(sex);//默认
//不同包中的继承类 protected public
System.out.println(hobby);
System.out.println(keyWord);
}
//不同包中的其他类 可访问 public
public static void main(String[] args) {
Demo6 d2=new Demo6();
// System.out.println(d2.name);//私有 private
// System.out.println(d2.sex);//默认
// System.out.println(d2.hobby);//protected
//不同包中的其他类 public
System.out.println(d2.keyWord);
}
}
package关键字
package 来解决命名冲突的问题 类的全名:包名 + 类名
包名可以有层次结构,一个类可以有多层包名
尽量包名和类名不要和jdk中的重名
import关键字
一般使用import语句导入这个类,然后使用该类
当出现不同包但类名同名冲突时,通过写全名[包名+类名] 来解决
常用的类在java.lang包中[java.lang.*] 则在java中不需要导入此包的类,可直接使用
其他类在用之前需要先导包,后才能使用此包的类 {导谁用谁,不全导}