final修饰局部变量:
* 基本数据类型:如果局部变量是一个基本数据类型,那么被final修饰,基本数据类型的变量的值不能再改变!
* 引用数据类型:如果用final修饰引用类型的变量,那么它不能在重写分配堆内存空间,但是可以改变可以成员变量的值
class Student{
int age ;
}
public class FinalTest {
public static void main(String[] args) {
//定义变量
int num = 10 ;
num = 100 ;
System.out.println("num:"+num);
System.out.println("-----------------------");
final int num2 = 200 ;
//基本数据类型的变量的值不能改变
// num2 = 100 ;
System.out.println("-----------------------");
Student s = new Student() ;
s.age = 100 ;
System.out.println(s.age);
System.out.println("------------------------");
final Student ss = new Student() ;
ss.age = 50 ;
System.out.println(ss.age);
ss.age = 56 ;
System.out.println(ss.age);
//不能重新分配堆内存空间
// ss = new Student() ;
}
}
一、多态
1、一个事物在不同时刻体现出来的不同状态:
水:固态,汽态 ,液态
Animal a = new Cat() ;
对于多态的三个前提条件
1)条件1:必须有继承关系(如果没有继承关系,谈不上多态!)
2)条件2:必须有方法重写
子类出现了父类一样的 方法声明
3)有父类引用指向子类对象:向上转型
Fu f = new Zi() ;
多态的三个条缺一不可!
多态的成员访问特点:
* (1) 成员变量:
* 编译看左边,运行看左边
* (2)成员方法(非静态的成员方法):
* 编译看左,运行看右;由于存在方法重写,所以就运行最终的就是子类的成员方法
* (3)静态成员方法:(静态方法算不上方法重写,静态直接跟类有关系!)
* 编译看左,运行看左
* (4)构造方法:还是对象进行初始化,由于是一种继承关系,还是分层初始化!
//父类
class Fu{
public int num = 10 ;
//父类的成员方法
public void show(){
System.out.println("show Fu...");
}
//静态方法
public static void function(){
System.out.println("function Fu....");
}
}
//子类
class Zi extends Fu{
int num = 20 ;
public void show(){
System.out.println("show Zi...");
}
public static void function(){
System.out.println("function Zi....");
}
}
//测试类
public class DuoTaiDemo {
public static void main(String[] args) {
//创建父类的对象:多态的形式
// 有父类引用指向子类对象:向上转型
Fu f = new Zi() ;
//访问成变量
System.out.println(f.num);
//调用成员方法:show()
f.show() ;
//静态方法
f.function() ;
}
}
2、多态的好处(特点):
* 1)提高代码的维护性(由继承保证)
* 2)提高代码的扩展性(由多态保证)
* java的开发原则:低耦合,高内聚
//写一个动物的工具类
class AnimalTool{
//将类中无参构造私有化:目的是为了不让外界创建对象!
/*private AnimalTool(){
}*/
//形式参数是一个父类
public void useAnimal(Animal a){
a.eat() ;
a.sleep() ;
}
}
//父类
class Animal{
public void eat(){
System.out.println("eat");
}
public void sleep(){
System.out.println("sleep...");
}
}
//猫类
class Cat extends Animal{
public void eat(){
System.out.println("猫吃鱼...");
}
public void sleep(){
System.out.println("猫趴着睡...");
}
}
//狗类
class Dog extends Animal{
public void eat(){
System.out.println("狗吃骨头...");
}
public void sleep(){
System.out.println("狗躺着睡....");
}
}
public class DuoTaiDemo2 {
public static void main(String[] args) {
//我喜欢猫,养一只猫
Cat c1 = new Cat() ;
c1.eat() ;
//还喜欢猫,又养了一只
Cat c2 = new Cat() ;
c2.eat() ;
//...
Cat c3 = new Cat() ;
c3.eat() ;
System.out.println("---------------------");
//优化改进:将猫的吃和睡的方法封装成独立的功能
/*useCat(c1) ;
useCat(c2) ;
useCat(c3) ;*/
Dog d1 = new Dog() ;
Dog d2 = new Dog() ;
Dog d3 = new Dog() ;
//调用狗的功能
/*useDog(d1) ;
useDog(d2) ;
useDog(d3) ;*/
System.out.println("------------------------");
//最终版代码
//先创建AnimalTool对象
AnimalTool at = new AnimalTool() ;
at.useAnimal(c1) ;//形式参数:Animal a = new Cat();
at.useAnimal(c2) ;
at.useAnimal(c3) ;
System.out.println("-------------------------");
at.useAnimal(d1) ;
at.useAnimal(d2) ;
at.useAnimal(d3) ;
}
3、多态的弊端:
不能访问子类的特有功能
class Animal2{
public void show(){
System.out.println("show Animal2...");
}
}
//子类
class Cat2 extends Animal2{
public void show(){
System.out.println("show Cat2....");
}
//特有功能
public void playGame(){
System.out.println("猫玩毛线...");
}
}
//测试类
public class DuoTaiDemo3 {
public static void main(String[] args) {
//多态的形式:父类引用指向子类对象
Animal2 a = new Cat2() ;
a.show() ;
// a.playGame() ;
}
}
4、多态的弊端如何解决?
* 解决方案:
* 1)创建子类的具体对象,来访问自己的特有功能;虽然可以解决多态的弊端,但是从内存角度考虑,需要创建子类对象,那么必须在堆内存开辟空间,
* 耗费内存,浪费空间!
* 2)既然多态的第三个前提条件:父类引用指向子类对象,那么可不可以将子类的引用指向父类对象呢?
* 可以的:向下转型:将父类的引用强制转换为子类的引用:前提必须有父类的引用存在;
* 向下转型必须依赖于向上转型!
class Animal3{
public void show(){
System.out.println("show Animal2...");
}
}
//子类
class Cat3 extends Animal3{
public void show(){
System.out.println("show Cat2....");
}
//特有功能
public void playGame(){
System.out.println("猫玩毛线...");
}
}
public class DuoTaiDemo4 {
public static void main(String[] args) {
//父类引用指向子类对象
Animal3 a = new Cat3() ; //向上转型
a.show() ;
//不能访问子类特有功能
// a.playGame();
//创建子类具体对象
/* Cat3 c = new Cat3() ;
c.playGame() ;*/
//父类的引用强制转换为子类的引用:向下转型
Cat3 c = (Cat3) a ;
c.playGame() ;
}
}
例:孔子装爹案例:
class 孔子爹{
public int age = 40 ;
public void teach(){
System.out.println("讲解JavaSE...");
}
}
//java培训很火,某一天孔子爹被请去讲课了,孔子粘上胡子,换上爹的装备,开始装爹!
class 孔子 extends 孔子爹{
public int age = 20 ;
public void teach(){
System.out.println("讲解论语...");
}
//特有功能
public void playGame(){
System.out.println("王者农药...");
}
}
//使用多态的前提条件:
父类的引用指向子类对象
孔子爹 k爹 = new 孔子() ;
System.out.println(k爹.age) ;//40------->编译看左,运行看左
k爹.teach() ;----->//讲论语;编译看左,运行看右
//向下转型
孔子 k = (孔子)k爹;
k.playGame();访问子类的特有功能
6、练习
(1)看程序写结果
class A {
public void show() {
show2();
}
public void show2() {
System.out.println("我");
}
}
class B extends A {
/**
* public void show(){
* show2() ;
* }
* */
public void show2() {
System.out.println("爱");//爱
}
}
class C extends B {
public void show() {
super.show();
}
public void show2() {
System.out.println("你");//你
}
}
public class DuoTaiTest {
public static void main(String[] args) {
A a = new B();
a.show();
B b = new C();
b.show();
// 2)爱你
}
}
有继承关系:
* 分层初始化:父类先初始化,然后子类初始化
* 多态的访问特点:
* 成员方法:(非静态的):编译看左,运行看右(方法重写)
(2)练习多态
class Person{
public void eat(){
System.out.println("eat");
}
}
//南方人
class SourthPerson extends Person{
public void eat(){
System.out.println("南方人喜欢吃米饭...");
}
//特有功能
public void business(){
System.out.println("南方人爱经商....");
}
}
//北方人
class NorthPerson extends Person{
public void eat(){
System.out.println("北方人爱吃馒头...");
}
//特有功能
public void yanJiu(){
System.out.println("北方人爱研究....");
}
}
//测试类
public class DuoTaiTest3 {
public static void main(String[] args) {
//多态版测试
Person p = new SourthPerson() ;
p.eat() ;
// p.business() ;
SourthPerson sp = (SourthPerson) p ;
sp.eat() ;
sp.business() ;
System.out.println("------------------");
//测试北方人
Person p2 = new NorthPerson() ;
p2.eat() ;
NorthPerson np = (NorthPerson) p2 ;
np.yanJiu() ;
}
}
二、 抽象类
1、概念
* 每一个动物的吃和睡的功能不一样,不应该把动物类定义为一个具体类,而是给出一个声明(abstract)
* 当一个类中如果有抽象功能(抽象方法)的时候,那么这个类一定要定义为抽象类!
*
* 问题:一个抽象类中可以有非抽象方法吗?
* 一个抽象类中可以抽象,也可以有非抽象的(作为一个判断题记忆!)
*
* 抽象类不能实例化:抽象类不能创建对象
* 一个抽象类如何进行实例化:
* 通过抽象类多态形式:父类的引用指向子类对象,通过子类进行初始化!
* 抽象类的子类的特点:
*
* 1)抽象类的子类是抽象类,那么没有意义!
* 最终使用的就是通过子类进行对象初始化的,如果子类都被抽象修饰了,那么也不能创建对象,所以没意义
*
* 抽象类多态:
* 强制子类必须重写当前抽象的父类中所有的抽象方法
* 还可以提高代码的维护性(里面继承关系保证!)
abstract class Animal{
//抽象方法:没有方法体的一个方法
public abstract void eat() ;
public abstract void sleep() ;
//具体方法
/*public void eat(){
System.out.println("eat");
}*/
public void show(){
System.out.println("show Animal....");
}
}
//抽象的子类
//abstract class Cat extends Animal{
//
//}
//子类是具体类
class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void sleep() {
System.out.println("猫趴着睡觉..");
}
}
//测试类
public class AbstractDemo {
public static void main(String[] args) {
//当前Animal已经被abstract修饰了
// Animal a = new Animal();//Cannot instantiate the type Animal:抽象类不能实例化:instaceof
//多态:父类引用指向子类对象
Animal a = new Cat() ; //Animal是抽象类,---->抽象类多态形式
a.eat() ;
a.sleep() ;
}
}
2、抽象类的成员特点
* 成员变量:
* 可以是变量也可以是自定义常量
* 构造方法:
* 抽象类可以有构造方法:包括有参构造和无参构造
* 作用:通过抽象类多态的形式:让子类进行数据的初始化
* 成员方法:
* 可以有抽象方法,也可以有非抽象方法
*
* 抽象类的成员方法特性:
* 抽象方法:强制子类必须要做到一件事情:方法重写(覆盖)
* 非抽象方法:由继承保证可以去提高代码的复用性
abstract class Fu{
private String name ;
private int age ;
//成员变量
public int num = 100 ;
public final int num2 = 200 ; //被final修饰:自定义常量
//无参构造
public Fu(){
}
//有参构造
public Fu(String name,int age){
this.name = name ;
this.age = age ;
}
//抽象方法
public abstract void show();
//非抽象方法
public void function(){
System.out.println("function Fu...");
}
}
//子类
class Zi extends Fu{
@Override
public void show(){
System.out.println("show Zi....");
}
}
//测试类
public class AbstractDemo2 {
public static void main(String[] args) {
//抽象类多态:
//抽象类的类名 对象名= new 子类名() ;
Fu f = new Zi() ;
f.show() ;
f.function() ;
}
}
3、问题:
* 一个类中如果没有抽象方法,那么这个类可不可以定义为一个抽象类呢?
* 可以!为什么
* 不能让其创建对象!
*
* abstract不能和哪些关键字共同使用?
* private 和abstract不能共同使用
* final和abstract不能共同使用
* static和abstract不能共同使用
*
* 实际开发中:public 公共访问权限
三、接口
1、接口的概念:
* 接口体现的是一种:扩展功能: 比如:猫可以跳高(并不是所有的猫都具有跳高功能)
*
* 如何表示接口:
* interface:接口 interface 接口名{
*
* }
* 接口里面的方法只能是抽象方法
* 接口中不能有构造方法
* 接口的特点:不能实例化(不能直接创建对象)
* 接口如何实例化:
* 接口的子实现类:
* 1)接口的子实现类是抽象类,没有意义,子类都不能创建对象了;实际开发中用的就是子类的对象进行初始化!
* 2)接口的子实现类是非抽象类
* 接口的实例化:就是通过子实现类对数据进行初始化!
*
* 接口的子实现类和接口的关系:implements:
* 格式:
* class 子实现类名 implments(实现) 接口名{
*
* }
//定义跳高的接口
interface Jump{
//非抽象方法:抽象类中不能有抽象方法
// public void jump(){
// System.out.println("猫可以跳高了...");
// }
public abstract void jump() ;
//构造方法:不能有
// public Jump(){
//
// }
}
//子实现类是抽象类类
//abstract class Cat implements Jump{
//子实现类是非抽象类
class Cat implements Jump{
@Override
public void jump() {
System.out.println("猫可以跳高了...");
}
}
//测试类
public class InterfaceDemo {
public static void main(String[] args) {
//创建接口对象
// Jump j = new Jump() ;//接口不能实例化
//接口多态:接口的引用指向子实现类对象
Jump j = new Cat() ;
j.jump();
}
}
2、接口成员的特点:
* 成员变量:
* 只能是常量:存下默认修饰符:public static final (永远建议自己给出默认修饰符)
* 构造方法:
* 接口是没有构造方法的
* 成员方法:
* 接口中的成员方法默认修饰符:public abstract(永远建议自己给出默认修饰符)
*
* 类,抽象类,接口
//定义一个接口
interface Inter{
public static final int num = 100 ;
public static final int num2 = 200 ;
//抽象方法
// public void show();
// void show() ;
//全部给出默认修饰符
public abstract void show() ;
//接口没有构造方法
// public Inter(){
//
// }
public abstract void function() ;
}
//定义接口的子实现类:见名知意:接口名+impl
class InterImpl implements Inter{
@Override
public void show() {
System.out.println(num);
System.out.println(num2);
}
@Override
public void function() {
System.out.println("function InterImpl...");
}
}
//测试类
public class InterfaceDemo2 {
public static void main(String[] args) {
//创建接口对象:接口多态的形式
Inter i = new InterImpl() ;
// i.num = 20 ;//当前num变量:被final修饰
System.out.println(Inter.num);//接口名.成员变量(当前变量被static修饰)
System.out.println(Inter.num2);
System.out.println("-------------");
i.show() ;
i.function() ;
}
}
3、类与接口二者的关系:
*(1)类与类的关系:
* 继承关系:extends,java中只支持单继承,不支持多继承,但是可以多层继承!
*(2) 类与接口的关系
* 实现关系:implements,并且,一个类在继承另一个类的同时,可以实现多个接口
* (class 子实现类名 enxtends Object implements 接口名1,接口名2…)
*
* (3)接口与接口的关系
* 继承关系:extends,可以支持单继承,也可以多继承!
interface Inter2{
}
interface Inter3{
}
//接口与接口的关系:extends
interface Zi extends Inter2{}
interface Son extends Inter2,Inter3{}
//子实现类
class InterImpl2 extends Object implements Inter2,Inter3{
}
public class InterfaceDemo3 {
}
四、练习
1、 猫狗案例
*加入跳高的额外功能
* 分析:具体到抽象
* 猫:
* 成员变量:姓名,年龄
* 构造方法:有参/无参
* 成员方法:setXXX()/getXXX()
* eat(),sleep()
* playGame()
* 狗:
* 成员变量:姓名,年龄
* 构造方法:有参/无参
* 成员方法:setXXX()/getXXX()
* eat(),sleep()
* lookDoor()
*
* 抽取一个独立的类:动物类:Animal类:抽象类 eat();抽象功能
*
* 猫继承自Animal
* 狗继承自Animal
*
* 部分猫和狗具有跳高功能:
* 接口: Jump
* 跳高的抽象功能
*
* 实现:抽象–>具体
public class InterfaceTest {
public static void main(String[] args) {
//实现接口的类是最具体的类,里面的功能最多:创建该类对象
//测试类跳高猫
JumpingCat jc = new JumpingCat() ;
jc.setName("Tom") ;
jc.setAge(5) ;
String name = jc.getName() ;
System.out.println(name);
// System.out.println(jc.getName()+"---"+jc.getAge());
jc.eat() ;
jc.sleep() ;
jc.playGame() ;
jc.jump() ;
System.out.println("--------------------");
//通过有参构造进行数据初始化
jc = new JumpingCat("加菲猫", 5) ;
System.out.println(jc.getName()+"---"+jc.getAge());
jc.eat() ;
jc.sleep() ;
jc.playGame() ;
jc.jump() ;
}
}
//动物的抽象类
public abstract class Animal {
//成员变量
private String name ;
private int age ;
public Animal() {
super();
}
public Animal(String name, int age) {
super();
this.name = name;
this.age = age;
}
//setXXX/getXXX()
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//抽象功能
public abstract void eat() ;
//非抽象
public void sleep(){
System.out.println("困了就需要休息...");
}
}
public class Cat2 extends Animal {
public Cat2() {
super();
}
public Cat2(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("猫吃鱼...");
}
public void playGame(){
System.out.println("猫玩游戏....");
}
}
public class Dog2 extends Animal {
public Dog2() {
super();
}
public Dog2(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("狗吃骨头....");
}
public void lookDoor(){
System.out.println("狗看门....");
}
}
//跳高接口
public interface Jumping {
//抽象功能
public abstract void jump();
}
//部分跳高猫首先应该是猫的一种,然后会跳高所以需要实现接口,重写里面的jump()方法
public class JumpingCat extends Cat2 implements Jumping {
public JumpingCat() {
super();
}
public JumpingCat(String name, int age) {
super(name, age);
}
@Override
public void jump() {
System.out.println("猫可以跳高了...");
}
}
//部分跳高狗
public class JumpingDog extends Dog2 implements Jumping {
public JumpingDog() {
super();
}
public JumpingDog(String name, int age) {
super(name, age);
}
@Override
public void jump() {
System.out.println("狗可以跳高了....");
}
}
2、老师案例
具体事物:基础班老师,就业班老师
共性:姓名,年龄,讲课。
分析:从具体到抽象:
基础班老师:
成员变量:姓名,年龄
构造方法:有参构造方法/无参构造方法
成员方法:SetXXX()/GetXXX():公共访问方法
teach(),eat()
就业班老师:
成员变量:姓名,年龄
构造方法:有参构造方法/无参构造方法
成员方法:SetXXX()/GetXXX():公共访问方法
teach(),eat()
将共性内容:抽取为一个独立类:老师类(抽象类): teach();每一个老师讲的内容不一样,应该定义为抽象功能;
代码的实现:
从抽象到具体
public class AbstractTest2 {
public static void main(String[] args) {
//测试基础班老师
Teacher t = new BasicTeacher() ;
t.setName("高圆圆") ;
t.setAge(27) ;
t.show();
System.out.println(t.getName()+"----"+t.getAge());
//调用功能
t.sleep() ;
t.teach() ;
System.out.println("------------------------");
//方式2:有参构造
t = new BasicTeacher("唐嫣",27) ;
System.out.println(t.getName()+"----"+t.getAge());
//调用功能
t.sleep() ;
t.teach() ;
}
}
public abstract class Teacher {
//成员变量
private String name ;
private int age ;
//无参
public Teacher() {
}
//有参
public Teacher(String name, int age) {
super();
this.name = name;
this.age = age;
}
//SetXXX/GetXXX()公共访问方法(alt+shift+s-->r)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//teach()
public abstract void teach() ;
//非抽象方法
public void sleep(){
System.out.println("困了,就需要休息....");
}
public void show(){
System.out.println(name+"---"+age);
}
}
//就业班老师类
public class WokeTeacher extends Teacher {
//有参
public WokeTeacher() {
super();
}
//无参
public WokeTeacher(String name, int age) {
super(name, age);
}
@Override
public void teach() {
System.out.println("就业班老师讲JavaEE...");
}
}
//基本班的老师类
public class BasicTeacher extends Teacher {
//alt+shift+s-->c
public BasicTeacher() {
super();
}
public BasicTeacher(String name, int age) {
super(name, age);
}
@Override
public void teach() {
System.out.println("基础班老师教JavaSE...");
}
}
3、经理案例
假如我们在开发一个系统时需要对员工类进行设计,程序员包含3个属性:姓名、工号(String)以及工资。(salary)
经理也是员工,除了含有员工的属性外,另为还有一个奖金属性。(bonus)
请使用继承的思想设计出程序员类和经理类。要求类中提供必要的方法进行属性访问。
分析:
具体到抽象
程序员类:Programmer
成员变量:姓名,工号,工资
构造:有参,无参
成员方法:
setXXX()/getXXX(),
worke()
经理类:Manager
成员变量:姓名,工号,工资
额外的属性:奖金
构造:有参,无参
成员方法:
setXXX()/getXXX(),
worke()
抽取共性内容:独立的类:Employee(抽象类) 普通员工和经理做的事情不一样,work();抽象方法
测试类:
代码的实现:从抽象到具体
员工类(抽象类)
普通员工(程序员类)
经理类
public class AbstractTest {
public static void main(String[] args) {
//测试程序员类
Employee emp = new Programmer() ;
emp.setName("高圆圆") ;
emp.setEmpId("xbky9527");
emp.setSalary(8000) ;
System.out.println(emp.getName()+"---"+emp.getEmpId()+"----"+emp.getSalary());
emp.work() ;
System.out.println("------------------");
//方式2:构造方法进行赋值
emp= new Programmer("张三","xbky008",10000) ;
System.out.println(emp.getName()+"---"+emp.getEmpId()+"----"+emp.getSalary());
emp.work() ;
System.out.println("------------------");
//测试经理类
// Employee emp2 = new Manager("李四", "xbky007", 10000, 2000) ;
//如果一个类有自己的特有属性:
// Employee emp2 = new Manager() ;
// emp2.setName("李四") ;
// emp2.setEmpId("xbky007");
// emp2.setSalary(10000) ;
emp2.setBouns(2000) ;
//创建经理类对象
Manager m = new Manager() ;
m.setName("李四") ;
m.setEmpId("xbky007");
m.setSalary(10000);
m.setBonus(2000);
System.out.println(m.getName()+"----"+m.getEmpId()+"----"+m.getSalary()+"---"+m.getBonus());
//构造方法进行初始化:
}
}
//抽象的员工类
public abstract class Employee {
//成员变量
private String name ;
private String empId ;
private int salary ;
//无参
public Employee() {
super();
}
//有参构造
public Employee(String name, String empId, int salary) {
super();
this.name = name;
this.empId = empId;
this.salary = salary;
}
//setXXX/getXXX()
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmpId() {
return empId;
}
public void setEmpId(String empId) {
this.empId = empId;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
//抽象的功能
public abstract void work() ;
}
//经理类
public class Manager extends Employee {
//有奖金属性
private int bonus ;
public Manager() {
super();
}
public Manager(String name, String empId, int salary,int bonus) {
super(name, empId, salary);
this.bonus = bonus ;
}
//奖金属性的setXXX/getXXX()
public int getBonus() {
return bonus;
}
public void setBonus(int bonus) {
this.bonus = bonus;
}
//工作
@Override
public void work() {
System.out.println("经理类和客户谈需求...");
}
}
//普通员工:程序员类
public class Programmer extends Employee {
//无参/有参
public Programmer() {
super();
}
public Programmer(String name, String empId, int salary) {
super(name, empId, salary);
}
@Override
public void work() {
System.out.println("程序员根据需求日日夜夜Coding");
}
}
五、回顾
1、代码块
class Student {
static {
System.out.println("Student 静态代码块");
}
{
System.out.println("Student 构造代码块");
}
public Student() {
System.out.println("Student 构造方法");
}
}
//测试类
class StudentDemo {
static {
System.out.println("高圆圆都38了,我很伤心");
}
public static void main(String[] args) {
System.out.println("我是main方法");
Student s1 = new Student();
Student s2 = new Student();
}
}
静态的代码:随着类的加载而加载:在内存中只加载一次
静态代码,构造代码,构造方法的执行顺序的问题:
优先级:静态代码>构造代码块>构造方法
"高圆圆都38了,我很伤心"
"我是main方法"
"Student 静态代码块"
"Student 构造代码块"
"Student 构造方法"
"Student 构造代码块"
"Student 构造方法"
2、接口和抽象类的区别
接口和抽象类的区别?
1)成员的区别:
成员变量:
抽象类:成员变量可以是常量,也可以是变量
接口:成员变量只能是一常量:存在默认修饰符:public static final
构造方法:
抽象类:可以有无参构造,有参构造方法
作用:通过子类进行数据初始化(通过子类创建对象)
接口:没有构造方法的
成员方法的区别:
抽象类:可以有抽象方法,也可以有非抽象方法
接口:只能是抽象方法:存在默认修饰符:public abstract
2)关系的区别:
类与类的关系:
继承关系:extends,java中只支持单继承,不支持多继承,但是可以多层继承!
类与接口的关系:
实现关系:implements,并且,一个类在继承另一个类的同时,可以实现多个接口
(class 子实现类名 enxtends Object implements 接口名1,接口名2…)
接口与接口的关系
继承关系:extends,可以支持单继承,也可以多继承!
3)设计理念的区别:
抽象类:
体现的是一种”is a”的关系,存在继承关系!(抽象类多态)
接口:
体现的是一种”like a”的关系,由于接口的一种扩展功能