1、构造代码块和静态代码块
静态代码块 -> 构造代码块 -> 构造方法
静态代码块当创建多个对象只会执行一次,而构造代码块创建多少个对象都会执行。
class Person{
private String name ;
private int age = 1;
//类属性,可以直接通过类直接访问
static String ancestor ="女娲";
{
System.out.println("构造代码块");
}
static {
System.out.println("静态代码块");
}
public Person() {
System.out.println("无参数构造方法");
}
public Person(String newname,int newage) {
this(); //必须在第一行
setName(newname);
setAge(newage);
}
public void setName(String newName) {
name = newName;
}
public String getName() {
return name;
}
public void setAge(int newage) {
if(newage >0 && newage<200) {
age = newage;
}
}
public int getAge() {
return age;
}
public void getInfo() {
System.out.println("ancestor:" + this.ancestor);
}
}
public class helloworld {
public static void main(String[] args) {
Person person1 = new Person("张三",22);
Person person2 = new Person("李四",25);
}
}
静态代码块
构造代码块
无参数构造方法
构造代码块
无参数构造方法
2、继承
1、关键字 extends
2、java类只能单继承
3、子类不能直接访问父类的私有属性
4、super 表示父类对象
5、当实例化对象时,会默认先调用父类的无参构造方法Super( ),再调用子类的构造方法;可以在子类构造方法中,通过super(参数)来调用父类的有参数构造方法。
class Person{
private String name ;
private int age = 1;
//类属性,可以直接通过类直接访问
static String ancestor ="女娲";
public Person() {
System.out.println("Person无参数构造方法");
}
public Person(String newname,int newage) {
//this(); //必须在第一行
System.out.println("Person的有参构造");
setName(newname);
setAge(newage);
}
public void setName(String newName) {
name = newName;
}
public String getName() {
return name;
}
public void setAge(int newage) {
if(newage >0 && newage<200) {
age = newage;
}
}
public int getAge() {
return age;
}
public static void setAncestor(String ancestor) {
Person.ancestor = ancestor;
}
public static String getAncestor() {
return ancestor;
}
public void print_info() {
System.out.println("name:"+name+"\nage:"+age);
}
}
class Student extends Person{
public Student(){
super("张三",18);
System.out.println("Student无参构造方法");
}
public Student(String newname) {
System.out.println("Student的有参构造方法");
}
}
public class helloworld {
public static void main(String[] args) {
Student stu1 = new Student();
stu1.print_info();
}
}
Person的有参构造
Student无参构造方法
name:张三
age:18
执行顺序:
1、在类中,如果普通成员变量未初始化,会帮我们默认初始化成员变量。
2、在单个类中,静态成员变量初始化 > 静态代码块执行 >普通成员变量初始化 > 构造代码块的执行 > 构造方法执行> 普通方法的执行
在继承关系中,父类静态变量初始化 > 父类静态代码块执行 > 子类静态变量初始化 > 子类静态代码块执行 >
父类普通成员变量初始化 >父类构造代码块的执行 >父类构造方法执行 > 子类普通成员变量初始化 > 子类构造代码块的执行 > 子类构造方法执行
class Person{
private String name ;
private int age;
private static int sex;
//类属性,可以直接通过类直接访问
static String ancestor ="女娲";
public Person() {
System.out.println("父类Person无参数构造方法");
}
{
System.out.println("父类Person成员变量:" + age);
System.out.println("父类Person构造代码块");
}
static {
System.out.println("父类Person静态成员变量:" + sex);
System.out.println("父类Person静态代码块");
}
public Person(String newname,int newage) {
//this(); //必须在第一行
System.out.println("父类Person的有参构造");
setName(newname);
setAge(newage);
}
public void setName(String newName) {
name = newName;
}
public String getName() {
return name;
}
public void setAge(int newage) {
if(newage >0 && newage<200) {
age = newage;
}
}
public int getAge() {
return age;
}
public static void setAncestor(String ancestor) {
Person.ancestor = ancestor;
}
public static String getAncestor() {
return ancestor;
}
public void print_info() {
System.out.println("name:"+name+"\nage:"+age);
}
}
class Student extends Person{
private int credit;
private static int school;
public Student(){
System.out.println("子类Student无参构造方法");
}
{
System.out.println("子类Student成员变量:" + credit);
System.out.println("子类Student构造代码块");
}
static {
System.out.println("子类Student静态成员变量:"+school);
System.out.println("子类Student静态代码块");
}
public Student(String newname) {
System.out.println("子类Student的有参构造方法");
}
}
public class helloworld {
public static void main(String[] args) {
Student stu1 = new Student();
}
}
父类Person静态成员变量:0
父类Person静态代码块
子类Student静态成员变量:0
子类Student静态代码块
父类Person成员变量:0
父类Person构造代码块
父类Person无参数构造方法
子类Student成员变量:0
子类Student构造代码块
子类Student无参构造方法
覆写 override 在继承关系中,子类方法名称,参数类型和个数,返回值类型完全相同
可以通过this和super调用方法和属性,使用this.方法 如果找不到就会在父类中寻找。
重载 overload 方法名称相同,参数类型和个数不同 在一个类中
public class Math {
public int add(int x,int y) {
return x + y;
}
public int add(int x,int y,int z) {
return x + y + z;
}
public static void main(String[] args) {
Math math = new Math();
int res1 = math.add(10, 20);
System.out.println("10 + 20 = "+ res1);
int res2 = math.add(10, 20,30);
System.out.println("10 + 20+ 30="+res2);
}
}
10 + 20 = 30
10+20+30=60
final关键字:
1、被final修饰的类不能被继承
2、被final修饰的方法不能被覆写
3、被final修饰的变量的值不能重新更改
public class Employee {
private final int id;
private String name;
private double wages;
private String department;
//构造方法 必须初始化final修饰的变量
public Employee(int id){
this(id,"无名氏",0,"未定");
}
public Employee(int id , String name){
this(id,name,1000,"后勤");
}
public Employee(int id,String name,int wages,String department){
this.id = id;
this.name = name;
this.wages = wages;
this.department = department;
}
public String getDepartment() {
return this.department;
}
public double getWages() {
return this.wages;
}
public int getId() {
return this.id;
}
public String getName() {
return this.name;
}
public static void main(String args[]) {
Manager manager = new Manager(1,"张三",20000,"前台",5000);
System.out.println("id:" + manager.getId()+"\nname:"+manager.getName() +
"\nwages:" + manager.getWages() + "\ndepartment:" + manager.getDepartment());
}
}
class Manager extends Employee{
private double bonus;
public Manager(int id,String name,int wages,String department,int bonus) {
super(id,name,wages,department);
this.setBonus(bonus);
}
//覆写 父类的方法
public double getWages() {
return super.getWages() + this.bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
public double getBonus() {
return this.bonus;
}
}
id:1
name:张三
wages:25000.0
department:前台
3、多态
置换法则:可以将子类对象赋值给父类变量。
一个对象变量可以引用多种实际类型的现象称为多态。
动态绑定:
public class TestA {
public void f(int x) {
System.out.println("f(int x)");
}
public void f(String x) {
System.out.println("f(String x)");
}
public static void main(String[] args) {
TestA A = new TestB();
A.f("String");
}
}
class TestB extends TestA{
public void f(String x) {
System.out.println("subclass f(String x)");
}
}
subclass f(String x)
1、首先,java编译器会先通过方法名和声明类型找到可能会调用的方法:
TestA.f(int x) 和TestA.f(String x)
2、然后根据参数类型,进行重载解析,找到调用哪一个重载方法:TestA.f(String x)
3、如果方法通过private,static,final修饰和构造方法,就会直接调用父类方法,这种调用称其为静态绑定。如果不是就查看实例对象的实际类型,并且在运行时实现动态绑定。编译器通过动态绑定的方式执行f(String x)指令。
4、当程序运行时,并且采用动态绑定调用方法时,虚拟机一定调用与实例对象的实际类型最适合的方法。
声明类型叫编译时类型,实际类型叫运行时类型
C c = new D(); C 是编译时类型,D是运行时类型;
在执行时,会收集实际类型的方法表,查找是否有f(String x)方法,没有就执行编译类型中的方法表中的方法。
运行时类型可以和编译时类型相同,也可以是编译时类型的任何子类。
引用类型强制转换:
当父类中没有子类的方法是,会报错,因为编译时,编译类型中找不到该方法,可以将类型强制转换成对象实例类型,就可以调用该方法。
引用类型转换只能发生在继承关系中。
public class Employee {
private final int id;
private String name;
private double wages;
private String department;
//构造方法 必须初始化final修饰的变量
public Employee(int id){
this(id,"无名氏",0,"未定");
}
public Employee(int id , String name){
this(id,name,1000,"后勤");
}
public Employee(int id,String name,int wages,String department){
this.id = id;
this.name = name;
this.wages = wages;
this.department = department;
}
public String getDepartment() {
return this.department;
}
public double getWages() {
return this.wages;
}
public int getId() {
return this.id;
}
public String getName() {
return this.name;
}
public static void main(String args[]) {
Employee e1 = new Manager(1,"张三",20000,"前台",5000);
//可以强转 因为e1是Manager类的实例对象
Manager m1 = (Manager)e1;
//不可以进行强转,因为e2不是Manager类的实例对象
Employee e2 = new Employee(1,"张三",20000,"前台");
Manager m2 = (Manager)e2;
}
}
class Manager extends Employee{
private double bonus;
public Manager(int id,String name,int wages,String department,int bonus) {
super(id,name,wages,department);
this.setBonus(bonus);
}
//覆写 父类的方法
public double getWages() {
return super.getWages() + this.bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
public double getBonus() {
return this.bonus;
}
}