static
表示静态关键字,可以用来修饰成员变量
和成员方法
。
被 static
修饰的成员变量,称之为静态成员变量
或者类变量
,同理可得,被修饰的成员方法称之为静态成员方法
或者类方法
。
public static String name="shawn";
void test(){
System.out.println(name);
System.out.println(Study08Static.name);
}
一般情况下,使用类名
直接来访问类变量
。
被 static 修饰的关键字的特点:
属于类,与类一起加载,在内存中只有一份,会被类的所有对象共享
使用 extends 关键字,可以让一个类与另一个类建立起父子关系。
继承的特点:
@Data
public class Pupil extends Student {
private String className;
private String teacher;
}
Java 中不支持多继承,仅支持单继承,即只能继承一个多父类。
所有的类都默认继承了Object
类。
即子类重新实现父类中已存在的方法,称之为方法重写
重写父类方法需要使用 @Override
注解
public class Parent {
public void getName(){
System.out.println("shawn");
}
}
//*********************************************
public class Son extends Parent {
@Override
public void getName() {
System.out.println("alice");
}
}
在子类范围访问父类的方法,如果已经对该方法进行了重写,则必须使用 super 关键字访问。
子类的全部构造器,都会先调用父类的构造器,再执行自己。
如果父类有多个构造器,则可以显示声明需要调用哪个构造器。
也可以使用 this
关键字,调用兄弟构造器
public class Parent {
public Parent(){
// 使用 this 关键字调用兄弟构造器
this("shawn");
}
public Parent(String name){
System.out.println(name);
}
}
使用 super 或 this 关键字调用其他构造器时,super 或 this 必须放在第一行。由此可得, super 和 this 不能同时使用。
访问修饰符被来用限制类中的成员能够被访问的范围
。
private < 缺省 < protected < public
多态是在继承(extends)
、实现(implements)
情况下的一种现象,表现为:对象多态,行为多态。
People p1=new Student();
p1.work();
People p2=new Teacher();
p2.work();
其中,p1
与 p2
表现为对象多态
,而 p1.work()
和 p2.work()
表现为行为多态。
多态的特点:编译看左边,运行看右边
1.多态形式下,右边对象是解耦合的,更便于维护和扩展。
解释:右边的对象如果不好用,则直接更换对象即可,无需再改动其他代码
2.定义方法时,使用父类类型的形参,可以接收一切子类对象
,扩展性更强,更便利
3.多态的缺点:多态下的父类对象,无法使用子类的独有功能
People student=new Student();
student.work();
Student stu=(Student)student;
stu.test();
注意事项:编译阶段
的类型强转不会报错,但是运行阶段
如果发现两个类型不能相互转换则会抛出异常
建议:强转前最好使用 instanceof
关键字,判断当前对象的真实类型,然后再进行强转
People p1=new Student();
p1.work();
if(p1 instanceof Student){
Student stu=(Student)p1;
stu.test();
}
final 关键字,表示为”最终“的意思,一般可以用来修饰类,方法,变量。
注意:
如果 final 修饰基本类型的变量,则变量存储的数据
不能被改变。
如果 final 修饰引用类型的变量,则变量存储的地址
不能被改变,但是地址所指向的内容
是可以被改变的。
// 数组(引用类型)的地址所指向的内容可以改变
final int [] number={1,2,34};
number[2]=111;
// 数组(引用类型)的地址不能改变(以下示例会报错)
final int [] number={1,2,34};
number[2]=111;
int [] number2={1,2,3,4};
number=number2;
使用 static final
修饰的成员变量一般被称之为常量。
常量通常用于记录一些配置信息
,或是经常在项目中使用但是却不允许被修改的数据。
程序编译后,常量会被“宏替换”,即出现常量的地方都将会被替换为字面量,这样可以保证使用常量和使用字面量的性能是完全一样的。
宏替换是C/C++编程中的一个重要概念,它是在预处理阶段进行的一种文本替换机制。通过使用宏定义,可以将一段代码片段或常量定义替换为预定义的文本。
被 abstract
修饰的类,叫做抽象类
,其中 abstract
就是抽象的含义,abstract
关键字可以修饰 类
和 成员方法
基本语法: [访问修饰符] abstract [class关键字] 类名
@Data
public abstract class AbstractParent {
/**
* 抽象类中的抽象方法
*/
public abstract void getName();
public void getAge(){
System.out.println("抽象类中的非抽象方法");
};
/**
* 抽象类中的成员属性
*/
private String name;
}
abstract 修饰类,则该类就是抽象类,abstract 修饰方法,则该方法就是抽象方法(抽象方法必须存在于抽象类中)。
抽象方法只有方法定义,没有方法体!!!
抽象类最重要的特点:抽象类不能创建对象,仅作为一种特殊的父类,让子类继承并实现
父类直到每个子类都要做某个行为,但是每个子类要做的情况不一样。这种情况下就可以将父类定义为抽象类,交给子类去重写实现。
这样设计的抽象类,可以更好的支持多态。
模板方法设计模式主要用来解决方法中存在重复代码的问题
模版方法设计模式的写法:
以下是抽象类:
public abstract class AbstractParent {
/**
* 抽象类中的抽象方法
*/
public abstract void getName();
public abstract void getSex();
// 这里的getinfo()就是模板方法,
public final void getInfo(){
getName();
System.out.println("这是我的年龄啊");
getSex();
}
}
以下是抽象类的实现类:
public class ExtendsSon extends AbstractParent {
@Override
public void getName() {
System.out.println("这是名字");
}
@Override
public void getSex() {
System.out.println("这是性别");
}
}
演示示例:
public static void main(String[] args) {
AbstractParent abstractParent=new ExtendsSon();
abstractParent.getInfo();
}
为放置模板方法被重写,可以对模板方法添加final
关键字
Java提供了一个关键字 interface
,使用这个关键字可以用来定义接口。接口中包含成员变量,成员方法。
public interface A {
/**
* 在接口中定义的成员变量,默认为常量
*/
String studentName="Shawn";
/**
* 定义接口(省略访问修饰符,接口中定义的方法默认为抽象方法)
*/
void getName();
}
特点:接口不能创建对象,接口是用来被实现的
接口的好处:
JDK8以后,接口中新增的三种方法:
default
关键字修饰,默认会被 public
修饰,且JDK8以后开始支持private
修饰,只能在默认方法中使用,且JDK9
以后才开始支持public interface B {
/**
* 默认方法 必须使用 `default` 关键字修饰,默认会被 `public` 修饰
* @return
*/
default String getName(){
System.out.println("仅仅是测试");
getAge();
return "shawn";
}
/**
* 接口中的私有方法
*/
private void getAge(){
System.out.println("这是私有方法");
}
/**
* 接口中的静态方法
*/
static void getAge(){
System.out.println("接口中的静态方法");
}
}
增加以上三种方法的原因:
同时集成的多个接口中如果存在名称冲突的方法,此时则无法进行多继承。
如果接口中存在与实现类同名的默认方法,则优先调用接口中的默认方法