世事漫随流水,算来一梦浮生。
------DJ懒洋洋
一:代码块
1):普通代码块
普通代码块:定义在方法中的代码块。
public class test7{ public static void main(String[] args) { { int x=10; System.out.println(x++); } } }
2):构造代码块
构造代码块:一般放在类中的代码块
public class Student{ public String name; public int age; { this. name="李华"; this.age=18; } public static void main(String[] args) { Student student=new Student(); System.out.println(student.name); System.out.println(student.age); } }
即作用:对成员变量进行初始化。
3:静态代码块
静态代码块:即由static修饰的代码块,不加修饰符。一般用来对静态成员变量进行初始化。
public class Student{ public String name; public int age; public static String classRoom; { this. name="李华"; this.age=18; } static{ classRoom="301"; } public static void main(String[] args) { System.out.println(Student.classRoom); } }
那么,静态代码块,构造代码块,放在一起会执行哪一个?
public class Student{ public String name; public int age; public static String classRoom; { this. name="李华"; this.age=18; System.out.println("hehehe"); } static{ classRoom="301"; System.out.println("hahah"); } public static void main(String[] args) { System.out.println(new Student().name); System.out.println(new Student().age); System.out.println(Student.classRoom); } }
代码运行结果如下:
由上述代码可知,我们创建了两次对象,且这两次对象我们对他们的姓名和年龄利用构造代码块进行,在main函数中,我们先创建了两次对象,来调用其属性值,再通过类名调用其静态变量,通过打印得知,无论main函数先运行哪个,静态代码块总是先执行,再执行构造代码块,且静态代码块只执行一次。
二:继承
1): 继承:关键字
如下图所示:
我们可以抽出cat和dog共有的属性和成员行为,将其放到Animal类中。即cat和dog继承于Animal类。此时Animal为cat和dog的父类,cat和dog为Animal的子类。
官方术语:对共性进行所谓的抽取,把抽取的共性放到父类中,达到代码的复用。java常见的继承方式如下图所示:
public class Animal { public String name; public int age; public Animal() { } public Animal(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public Animal setName(String name) { this.name = name; return this; } public int getAge() { return age; } public Animal setAge(int age) { this.age = age; return this; } public void eat(){ System.out.println("吃东西"); } } class Dog extends Animal{ public Dog(){ super(); } public String id; public Dog(String name,int age,String id){ super(name,age); this.id=id; } public void eat(){ System.out.println(this.name+"在吃骨头"); } } class Cat extends Animal{ public Cat(){ } public Cat(String name,int age){ super(name,age); } public void eat(){ System.out.println(this.name+"在吃鱼"); } public static void main(String[] args) { Dog dog=new Dog("小旺旺",18,"1"); dog.eat(); Cat cat=new Cat("小花",19); cat.eat(); } }
运行结果:
如上述代码所示,我们实现了继承这一关系。但仍有很多注意的小点。
注意:
1:super关键字的使用,用来访问父类的成员变量和成员行为。
代码演示:
父类:
public void play(){ System.out.println("好好玩耍"); }
子类:
public Dog(){ super(); super.play(); }
注意:
1:父类的空参构造在子类中是默认的,即使不写,idea也会自动添加。
2:如果父类成员变量和子类成员变量的变量名重合时,优先访问子类的成员变量,非要访问父类的成员变量,则需要super关键字来进行访问。那么,继承了父类的成员变量,子类完成实参或者空参构造前,必须先给父类进行构造。该结构图是什么样的?
2):final关键字
final关键字,修饰类不能被继承,修饰常量不能被更改。
以如下代码为例:当final修饰Animal这个类时,狗类进行继承,发现编译器会报错。印证了上面的一点,由final修饰的类不能被继承。
final public class Animal { public String name; public int age; public Animal() { } public Animal(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public Animal setName(String name) { this.name = name; return this; } public int getAge() { return age; } public Animal setAge(int age) { this.age = age; return this; } } class Dog extends Animal{ }
以如下代码为例,发现由final修饰的变量会变为常量,且不能被修改。
public class Main { public static void main(String[] args) { final int a=10; a=120; } }
结果如下:
三: 多态
1):各个代码块的执行顺序:
1:当父类的静态代码块,子类的静态代码块,父类的实例代码块,子类的实例代码块,父类的构造代码块,子类的构造代码块放在一起,执行顺序是怎样的?
以如下代码为例:
public class Person { private String name; private int age; public static String livinghouse; //父类的静态代码块 static{ livinghouse="301"; System.out.println("父类的静态代码块"); } { System.out.println("父类的构造块"); } public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public Person setName(String name) { this.name = name; return this; } public int getAge() { return age; } public Person setAge(int age) { this.age = age; return this; } public static String eat(){ return "地球人都吃饭"; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } } class Student1 extends Person{ public String id; public Student1() { super(); } public Student1(String name, int age,String id) { super(name, age); this.id=id; } static{ System.out.println("我是子类静态代码块"); } { System.out.println("我是子类构造块"); } public String getId() { return id; } public Student1 setId(String id) { this.id = id; return this; } @Override public String toString() { return "Student1{" + "id='" + id + '\'' + '}'; } } class test1{ public static void main(String[] args) { Person person=new Person("小李",18); System.out.println(person); System.out.println(Person.livinghouse); System.out.println(Person.eat()); System.out.println("==============="); Student1 student=new Student1("小花",19,"10"); System.out.println(student); System.out.println("==============="); Student1 student1=new Student1("小明",20,"11"); System.out.println(student1); } }
以上述代码为例,我们来看执行顺序:
如上述代码运行结果如图:
1:先执行父类的静态代码块,再执行父类的构造块,再执行父类的实例化对象,再执行子类的静态代码块,父类的构造块,子类的构造块,再执行子类的实例化对象,且我们在创建第二个学生对象的同时,发现父类的静态代码块和子类的静态代码块只执行一次。
如上:静态代码块>构造块>实例化对象,父类的执行顺序>子类的执行顺序。
2):多态
1: 概念:同一件事情,发生在不同对象身上,会产生不同的效果。在实现多态之前,我们得先了解什么是重写
重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变
1:方法名相同
2:参数列表相同
3:返回值相同。
//父类的play方法 public void play(){ System.out.println("好好玩"); } //子类对父类的play方法进行重写 public void play(){ System.out.println("开心的玩耍"); }
哪些情况不能被重写?
1:被priavte修饰的方法不能被重写,因为private是私有化,且只能在本来中使用。
2:被static修饰的方法不能重写,因为static修饰的方法为静态方法,只能通过类名来调用。
3:子类的访问权限修饰符>=父类的权限修饰符
4:重写的方法所在的类不能被final修饰,即被final修饰的父类不能被子类继承。
5:父类的实参构造和空参构造不能被重写。
2):向上转型
如上图所示:即子类向父类进行转型,由小范围往大范围转,且子类必须对父类的方法进行重写,这就叫多态
代码如下:我们创建一个Animal的父类,创建猫和狗的子类来继承Animal的父类。
public class Animal { private String name; private int age; public Animal() { } public Animal(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public Animal setName(String name) { this.name = name; return this; } public int getAge() { return age; } public Animal setAge(int age) { this.age = age; return this; } public void eat(){ System.out.println("好好吃饭"); } } class Dog extends Animal{ String typeFood; public Dog() { super(); } public Dog(String name, int age,String typefood) { super(name, age); this.typeFood=typefood; } @Override public void eat(){ System.out.println(super.getName()+"在吃:"+this.typeFood); } } class Cat extends Animal{ String typefood; public Cat() { super(); } public Cat(String name, int age,String typefood) { super(name, age); this.typefood=typefood; } public void eat(){ System.out.println("可爱的"+super.getName()+"在吃:"+this.typefood); } } class test2{ public static void eat(Animal animal){ animal.eat(); } public static void main(String[] args) { eat(new Dog("小狗",12,"骨头")); eat(new Cat("小花",11,"猫粮")); } }
运行结果:
3):向下转型
代码如下:且需要强转,且不安全。
Dog dog=(Dog)new Animal();
今天就到这了,感谢各位大佬的捧场!!!欢迎各位大佬批评指正。