1.代码块
概念:使用{}括起来的代码称为代码块。
分类:根据它的位置和声明的不同,我们可以将代码块分为局部代码块,构造代码块,静态代码块和同步代码块(多线程涉及)。
a、局部代码块:限定了变量的生命周期,变量在局部代码块中定义的,那么出局部代码块之后就访问不到了,在局部代码块中定义的变量在出了代码块之后就会释放掉。
* 局部代码块中定义的变量,虽然作用是局部的,但是如果存在外部嵌套的代码块,且在局部代码块之前就定义了某个变量,那么在我们局部代码块中就不可以定义相同名称的变量。但是如果在局部代码块之后去定义一个和局部代码块中相同名称的变量是可以的,因为局部代码块中的变量已经失去了作用域范围。
作用: 节约内存 。
b、构造代码块:类中方法外出现,每次调用构造方法的时候都会优先先调用构造代码块。
特点: 每创建一个对象,都会调一次我们的构造代码块。
作用:如果存在很多重载的构造方法,而且每个里面需要执行相同的逻辑,那么就可以考虑将这些代码提取到构造代码块中来执行,让我们代码结构更简练,增强了维护性(但其实使用场景并不多见)。
c、静态代码块(类加载时会调用静态代码块): 类中方法外出现,用static修饰。
特点:随着类加载的时候执行
作用:适用于整个软件的生命周期中只需要执行一次的业务逻辑代码(比如之后的数据库操作)。
2.继承
*特点: a、子类继承父类,继承父类的成员变量和方法。但是他们各自拥有各自的成员变量,所以他们的值并不会继承。
b、对于父类中的私有成员变量和私有方法,子类时无法继承的。
*优点: a、提高了代码的复用性。
b、提高了代码的维护性。
*缺点:增强了类的耦合性
[开发的原则:高内聚,低耦合]
[内聚:自己独立完成某件事情的能力;耦合:类和类之间的关系]
* 只支持单继承,不支持多继承但是可以支持多层继承。继承是相互叠加的,子类继承的时候,会递归类似的寻找父类中是否还存在继承,会继承整个层级直到最根部类的属性和方法。
* 对于构造方法是无法继承的,但是有办法可以调用父类的构造方法。
package study07;
import java.util.*;
public class Employee {
public static void main(String [] args){
Employee employee = new Employee();
employee.SetName("syh");
employee.setSalary(6000);
employee.setBirthday(new Date());
Manager manager = new Manager();
manager.SetName("zst");
manager.setSalary(13000);
manager.setBirthday(new Date());
manager.setBonus(3000);
System.out.println("员工的姓名:"+employee.getName());
System.out.println("员工的工资:"+employee.getSalary());
System.out.println("员工的生日:"+employee.getBirthday());
System.out.println("经理的姓名:"+manager.getName());
System.out.println("经理的工资:"+manager.getSalary());
System.out.println("经理的生日:"+manager.getBirthday());
System.out.println("经理的奖金:"+manager.getBonus());
}
private String name;
private double salary;
private Date birthday;
String getName(){
return name;
}
void SetName(String name){
this.name=name;
}
double getSalary(){
return salary;
}
void setSalary(double salary){
this.salary = salary;
}
Date getBirthday(){
return birthday;
}
void setBirthday(Date birthday){
this.birthday = birthday;
}
}
class Manager extends Employee{
private double bonus;
double getBonus(){
return bonus;
}
void setBonus(double bonus){
this.bonus = bonus;
}
}
3.继承关系中访问成员变量:
a、不同名的成员变量:子类可以直接访问和使用父类继承的非私有的成员变量。
package study07;
public class Work4 {
public static void main(String[] args){
Son son = new Son();
System.out.println(son.num3);
son.print();
}
}
class Father{
int num1 = 10; //如果在父类的成员变量前加上private,那么子类将无法访问
int num2 = 20;
}
class Son extends Father{
int num3 = 30;
void print(){
System.out.println(num1+num2); //子类可以直接访问和使用父类继承的非私有成员变量
}
}
b、同名成员变量:(优先原则:如果子类中定义了和父类中相同名字的成员变量,会优先访问子类的该变量)如果依然要访问父类中的同名变量,我们需要加上super关键字来获取。
package study07;
public class Work5 {
public static void main(String[] args) {
City c = new City();
c.value();
}
}
class Country {
String name;
void value(){
name = "China";
}
}
class City extends Country {
String name;
void value() {
name = "陕西";
super.value(); //不调用此方法时,super.name返回的是父类的成员变量的值null,把成员变量name值赋为china,再利用super.name调用父类中成员变量的值
System.out.println(name);
System.out.println(super.name);
}
}
区分this和super关键字:
this:当前对象的引用,可以访问到子类中的变量,也可以访问到父类中的变量;可以访问子类的方法,也可以访问父类的方法。
super:父类对象的引用,访问父类中的变量;只能访问父类的方法。
继承关系中访问成员方法:
a、不同名的方法:子类可以直接调用父类的方法
b、同名的方法:当父类和子类出现同名方法的时候(同名方法:指返回值类型、方法名称以及方法接受的形参列表要一模一样),这种情况下,当我们子类调用该方法时,会有优先原则的处理,就是会调用子类的该方法。
4.方法重写与方法重载
方法重写:存在于继承关系中,当子类继承父类种中所有可能被子类访问的成员方法时,如果子类的方法名与父类的方法名相同,那么子类就不能继承父类的方法,此时称为子类的方法重写了父类的方法。
注意:
a、子类不能重写父类私有方法
b、子类重写父类方法的时候提供的访问权限不能更低
c、子类覆盖父类的方法,如果父类是静态方法的话,子类也必须是静态方法才可以成功覆盖,就是重写。
package study07;
public class Zoo {
public static void main(String[] args){
Dog dog = new Dog(); //创建Dog类的对象并为其分配内存
System.out.println("执行dog.cry();语句时的输出结果:");
dog.cry();
Cat cat = new Cat(); //创建Cat类的对象并为其分配内存
System.out.println("执行cat.cry();语句时的输出结果:");
cat.cry();
Sheep sheep = new Sheep(); //创建Sheep类的对象并为其分配内存
System.out.println("执行sheep.cry();语句时的输出结果:");
sheep.cry();
}
}
class Animal { //创建一个Animal类,在该类中声明一个成员方法cry()
public Animal(){
}
void cry(){
System.out.println("动物发出叫声!");
}
}
class Dog extends Animal{ //创建Animal的子类Dog,在该类中重写父类的成员方法cry()
public Dog(){
}
public void cry(){
System.out.println("狗发出”汪汪....“声!");
}
}
class Cat extends Animal{ //创建Animal的子类Cat,在该类中重写父类的成员方法cry()
public Cat(){
}
public void cry(){
System.out.println("猫发出”喵喵....“声!");
}
}
class Sheep extends Animal{ //创建Animal的子类Sheep,在该类中不定义任何方法
}
方法重载:在同一个类中,如果我们有多个相同的方法名的方法,但他们的形参列表是不同的,那么这种方式我们就称为方法重载。在调用的时候jvm能够同通过不同的形参来区别我们到底调用的是哪个方法。
class ChongZai{
public void a(int a);
public void a(Strting a);
public void a(int a,int b);
}
方法重写与方法重载返回值的约束:
重载:仅返回值不同是不能重载的,必须参数列表不同。
重写:返回值类型(父子关系是可以的),要求返回值类型也相同。
5.继承中构造方法的调用:
特点:a、创建子类对象的时候,一定会优先去创建父类的对象,所以就需要去调用父类的构造方法。
b、对于我们所有类的构造方法的第一行,第一行在我们没有自己添加this(……)或者super(……)的情况下都会去帮我们自动添加一个super().
如果父类中不存在默认构造,子类依然要创建对象,那么子类就需要显示的指明调用的是哪一个父类对象,才能保证父类对象创建成功。
明确:a、一定要保证父类的创建成功
b、构造方法的第一行,如果我们添加了自己调用的this(……)或者super(……),系统就不会为我们默认添加super().
c、我们的this(……)或者super(……)必须放在第一行,也就是说二者只能有其一。
6.final关键字
a、final修饰类,final修饰一个类,则该类不能被继承。也就是说,如果一个类你永远不会让他被继承,就可以用final进行修饰。final类中的成员变量可以根据需要设为final,但是要注意final类中的所有成员方法都会被隐式地指定为final方法。在使用final修饰类的时候,要注意谨慎选择,除非这个类真的在以后不会用来继承或者出于安全的考虑,尽量不要将类设计为final类。
b、final修饰成员变量,对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。
那么应该什么时候初始化这个值?
在创建对象之前都可以(三种方法:构造代码块中可以初始化/ 构造方法中可以初始化/定义成员变量的时候可以直接进行初始化 三种方法只能选一种)
c、大多数情况下,fianl成员变量都会配合public、static一起使用。
静态成员变量初始化的时机:
a、在创建静态final成员变量的时候直接进行初始化。
b、在静态代码块中进行初始化。
我们一个文件在编译后产生的.class文件的数量,取决于该文件中定义的class的数量(非内部类)。