面向对象06
instanceof和类型转换
(需要掌握的点全在代码里)
instanceof
instanceof是Java、php的一个二元操作运算符,和==,>,<是同一类东西。由于它是由字母组成的,所以也是Java的保留关键字。它的作用是判断其左边对象是否为其右边类的实例,返回boolean类型的数据。
用法:boolean result = object instanceof class
参数
result:布尔类型
object:必选项 任意对象表达式。
class:必选项 任意已定义的对象的类
说明:如果object是class的一个实例,则其返回值为true;如果object不是指定类的一个实例,或者object是null,则返回false。
关于instanceof的东西都放在启动类里,不分开写了,不然查看起来不方便.
public class Application {
public static void main(String[] args) {
//Object > Person > Student
//两边必须要有关联,否则直接编译报错(两者不一定是子父关系,但必须有关联,即可以是同级关系)
//System.out.println(X instanceof Y); 判断引用X指向的实际类型是不是Y的子类型,是true,不是false
Object object = new Student();
//true
System.out.println(object instanceof Student);
//true
System.out.println(object instanceof Person);
//true
System.out.println(object instanceof Object);
//false
System.out.println(object instanceof Teacher);
//false
System.out.println(object instanceof String);
System.out.println("========================");
Person person = new Student();
//true
System.out.println(person instanceof Student);
//true
System.out.println(person instanceof Person);
//true
System.out.println(person instanceof Object);
//false
System.out.println(person instanceof Teacher);
//编译报错
//System.out.println(person instanceof String);
System.out.println("==========================");
Student student = new Student();
//true
System.out.println(student instanceof Student);
//true
System.out.println(student instanceof Person);
//true
System.out.println(student instanceof Object);
//编译报错
//System.out.println(student instanceof Teacher);
//编译报错
//System.out.println(student instanceof String);
public class Person {
public void run(){
System.out.println("run");
}
}
public class Student extends Person{
public void go(){
System.out.println("go");
}
}
public class Teacher extends Person{
}
}
}
instanceof:
1.两边必须要有关系,否则直接编译报错(两者不一定是子父关系,但必须有关联,即可以是同级关系)
2.System.out.println(X instanceof Y); 判断引用X指向的实际类型是不是Y的子类型,是true,不是false
类型转换
1.启动类
public class Application {
public static void main(String[] args) {
//类型之间的转换:父 子
//高 低 低转高,自动转换 向上转型
Person obj = new Student();
//高转低,强制转换 向下转型
//将obj这个对象转换为Student类型,我们就可以使用Student类型的方法了
((Student) obj).go();
//子类转换为父类,可能会丢失自己本来的一些方法!(除重写以外的所有方法)
Student student = new Student();
Person person = student;
//person.go();
//重写方法run
person.run();
}
}
2.父类Person
public class Person {
public void run(){
System.out.println("run");
}
}
3.子类Student
public class Student extends Person{
public void go(){
System.out.println("go");
}
@Override
public void run() {
System.out.println("Student...run");
}
}
4.子类Teacher
public class Teacher extends Person{
}
static关键字
关于static继承里面的问题,最近一直在讲就不在这再赘述了,想不起来就看前面博客
1.静态修饰符static(有关属性和方法问题)
public class Student {
/**
* 静态的实例变量
* 一个静态实例变量对于这个类而言,只有这一个,它能被类中的所有实例去共享!(先做了解,多线程会再详细的去讲)
* 当我们需要很多类操作一个实例变量时,我们都会选择static关键词去修饰
*/
private static int age;
/**
* 非静态的实例变量
*/
private double score;
public void run(){
System.out.println("run");
}
public static void sleep(){
System.out.println("sleep");
}
public static void main(String[] args) {
Student stu = new Student();
//若只写stu.score,只是调到了,但没有接收或输出它,是无意义的!
//Student.score是不可以的 不能从静态上下文引用非静态字段“分数”
//stu.score 非静态变量score必须通过实例化的对象来调!
double score = stu.score;
System.out.println(score);
//System.out.println(stu.score); 将调用的打印输出
//若只写Student.age,同样也只是调到了,但没有接收或输出它,无意义!
//Student.age 静态变量age,通过类名Student来调
int age = Student.age;
System.out.println(age);
//System.out.println(Student.age); 将调用的打印输出
//静态方法直接调用,而同一类中,可省略类名
sleep();
//非静态方法必须首先创建类的对象,然后用其对象去调用
stu.run();
/*之前有说过,静态方法和类一起加载,在加载的时候还没有非静态方法,有调无,所以没法调!
类加载顺序的问题,后面在注解与反射的时候会讲类加载机制,到时候要认真听、吸收和思考,就理解了*/
}
}
2.静态修饰符static(静态代码块问题)
public class Person {
//第二步执行
{
System.out.println("匿名代码块");
//代码块(匿名代码块) 没有名字,程序在执行的时候并不能主动调用这些模块!
//它是创建这个对象的时候它就自动创建了,而且它在构造器之前! 可以用这一特点进行 赋初始值操作
}
//第一步执行
static {
System.out.println("静态代码块");
//静态代码块 跟类一加载,它就直接执行,整个过程只执行一次!
}
/**
* 第三步执行
*/
public Person() {
System.out.println("构造方法");
}
public static void main(String[] args) {
Person person1 = new Person();
//通过输出等号分割线,来验证静态代码块在整个过程中只执行一次
System.out.println("==============");
Person person2 = new Person();
}
}
3.静态导入包
package com.oop.demo11;
//静态导入包
import static java.lang.Math.random;
import static java.lang.Math.PI;
/**
* @author 1301450090@qq.com
* @date 2021/4/7 1:12
*/
public class Test {
public static void main(String[] args) {
//Math.random() 产生随机数的方法
//System.out.println(Math.random()); 通过静态导入包,我们这里的Math是可以省略的
System.out.println(random());
System.out.println(PI);
}
}
/*
* 一般没人这么去玩,讲静态导入包的目的是让我们明白,Java中的知识很多,只要你想学能学的东西太多啦!
* 不要学了点循环就以为自己了不得,不要做愚昧山峰最顶端的人,拒绝当巨婴,拒绝浮躁!!!
* 如果一个类被final修饰了,就没办法使其派生出子类了(final之后就断子绝孙啦--哈哈哈哈哈哈哈😄狂神说的)
*/
抽象类
关于抽象类,理解掌握以下内容就够了。由于类只能单继承,因此它不是我们的重点,重点是我们更多使用的接口(可以实现多继承)(紧接着后面会学)。
abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。
抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。
抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。
抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。
1.抽象类Action
package com.oop.demo12;
/**
* @author 1301450090@qq.com
* @date 2021/4/7 15:00
* 抽象类 被abstract修饰的类
* 在Java中,类只有单继承! 接口可以实现多继承!(后面要学,先做了解。)
* 举个栗子:将接口看作是“插座”,它只约束了插什么插头,但是并没有约束什么电器才能插上去
*/
public abstract class Action {
/**
* 约束---希望有人可以帮我们实现
* 被abstract修饰的方法,抽象方法,只有方法名字,没有方法的实现
*/
public abstract void doSomething();
//1.不能new这个抽象类,只能靠子类去实现它 它就是一个约束!
//2.抽象方法必须存在于抽象类中,但是抽象类中可以写有非抽象(普通)方法
//思考:抽象方法不能使用new关键字,那么它存在构造器吗?抽象类存在的意义是什么?
}
2.子类A
package com.oop.demo12;
/**
* @author 1301450090@qq.com
* @date 2021/4/7 15:06
* 对于抽象类而言,继承了它的子类,都必须要实现它的所有方法 除非将子类也用abstract修饰
*/
public class A extends Action{
@Override
public void doSomething() {
}
}
/*
若直接让A类仅去继承抽象类Action,而不做任何操作,则会编译报错
Class 'A' must either be declared abstract or implement abstract method 'doSomething()' in 'Action'
2.类"A"必须被声明为抽象
public abstract class A extends Action{
}
1.或者必须在"Action"中实现抽象方法"doSomething()"
我们通过方法重写来实现
*/
如果我的博客对你有一点点帮助,望请大侠可以给文章点个赞再走~
声明:因个人能力有限,博文中必有不足之处,望学术同仁不吝赐教!一起学习一起进步!
以上内容均为原创,转载请注明出处!