一、代码块(类中)
1.代码块的作用:
用来初始化类和对象
代码块如果要修饰的话,只能是static
//非静态代码块
{
......
}
//静态代码块
static{
......
}
2.非静态代码块(构造代码块)
内部可以有输出语句
随着对象的创建而执行,在构造方法之前(有些构造方法不一定执行)
每创建一个对象,就执行一次
可以在创建对象的时候,对对象的属性等进行初始化的操作
3.静态代码块
内部可以有输出语句
随着类的加载而执行,而且只执行一次
如果一个类定义了多个静态代码块,按照声明的先后顺序
4.代码块执行的顺序:
静态代码块-》构造代码块-》构造方法
由父及子,静态先行
public class Main {
public static void main(String[] args) {
new Leaf();
System.out.println();
new Leaf();
}
}
class Root{
static {
System.out.println("Root的静态代码块");
}
{
System.out.println("Root的普通代码块");
}
public Root(){
System.out.println("Root的无参构造器");
}
}
class Mid extends Root{
static {
System.out.println("Mid的静态代码块");
}
{
System.out.println("Mid的普通代码块");
}
public Mid(){
System.out.println("Mid的无参构造器");
}
public Mid(String msg){
this();
System.out.println("Mid的带参构造器,其参数值为:"+msg);
}
}
class Leaf extends Mid{
static {
System.out.println("Leaf的静态代码块");
}
{
System.out.println("Leaf的普通代码块");
}
public Leaf(){
super("holy~~");
System.out.println("Leaf的构造器");
}
}
Root的静态代码块
Mid的静态代码块
Leaf的静态代码块
Root的普通代码块
Root的无参构造器
Mid的普通代码块
Mid的无参构造器
Mid的带参构造器,其参数值为:holy~~
Leaf的普通代码块
Leaf的构造器
Root的普通代码块
Root的无参构造器
Mid的普通代码块
Mid的无参构造器
Mid的带参构造器,其参数值为:holy~~
Leaf的普通代码块
Leaf的构造器
5.属性可赋值的位置:
1默认初始化
2显式初始化
3构造器中初始化
4有了对象只后,进行赋值
5代码块中初始化
执行的先后顺序:1--2/5--3--4
二、final关键字
final表示最终的意思,可以用来修饰:类、属性、方法
(1)final修饰类:这个类就不能被继承了。例如:String类、System类等
(2)final修饰方法:这个方法就不能被重写了。
(3)final修饰变量,这个变量就称为是一个常量
变量有两种:
final修饰成员属性,可以考虑的赋值位置有显式赋值、代码块初始化、构造器初始化(不能通过方法初始化)
final修饰局部变量:表明此形参是一个常量,且只能在这个方法体中用,只能赋值一次。
public static final用来修饰属性:全局变量
三、抽象类
1.含义:
抽象类是它的所有子类的公共属性的集合,是包含一个或多个抽象方法的类。抽象类可以看作是对类的进一步抽象。
抽象类用abstract来修饰,abstract可以用来修饰类和方法
2.abstract修饰类:抽象类
此类不能被实例化,
抽象类中一定有构造器,便于子类实例化调用。因为子类对象实例化的时候和普通类的继承一样,都要先调用父类中的构造器。
3.abstract修饰方法:抽象方法
抽象方法只有方法的声明,没有方法体
包含抽象方法的类,一定是抽象类;但是抽象类不一定包含抽象方法
若子类重写了父类抽象类中的所有抽象方法以后,该子类可以被实例化
如果没有全部重写,该子类也是个抽象类,需要abstract修饰
4.注意:
abstract不能用来修饰:属性,构造器等结构
abstract不能修饰私有的方法,静态的方法,final的方法及类
抽象类必须用public或protected修饰,缺省下默认为public
抽象类不能用new来创建对象,但在子类创建对象的时候,抽象父类也会被JVM实例化。
5.匿名子类对象
public class Main
{
public static void main(String[] args){
//创建了一匿名子类的对象p
Person p = new Person() {
@Override
public void eat() {
System.out.println("吃饭");
}
@Override
public void breath() {
System.out.println("呼吸");
}
};
method(p);
}
private static void method(Person p) {
p.eat();//调用的是子类的方法
p.breath();
}
}
//抽象类
abstract class Person{
//抽象方法
public abstract void eat();
public abstract void breath();
}
练习:
定义Shape抽象类表示一般二维图形。Shape具有抽象方法area和perimeter,分别计算形状的面积和周长。试定义一些二维形状类(如矩形、三角形等),这些均为Shape类的子类并计算出这些形状的面积和周长,打印输出相关信息。
public class Main {
public static void main(String[] args) {
Rectangle rectangle = new Rectangle(3,2);
Triangle triangle = new Triangle(3,4,5);
System.out.println("矩形的面积为:"+rectangle.area()+" 周长为: "+rectangle.perimeter());
System.out.println("三角形的面积为:"+triangle.area()+" 周长为: "+triangle.perimeter());
}
}
//形状类
abstract class Shape{
public abstract double area();//面积
public abstract double perimeter();//周长
}
//矩形类
class Rectangle extends Shape{
private double length;
private double width;
public Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
@Override
public double area() {
return length * width;
}
@Override
public double perimeter() {
return 2 * (length + width);
}
}
//三角形类
class Triangle extends Shape{
private int a,b,c;
public Triangle(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
}
@Override
public double area() {
double p = (a + b + c) / 2;
return Math.sqrt(p * (p - a) * (p - b) * (p - c));
}
@Override
public double perimeter() {
return a + b + c;
}
}
矩形的面积为:6.0 周长为: 10.0
三角形的面积为:6.0 周长为: 12.0