Java基础Day09

day09

  1. 代码块
    1.1 代码块的概念
    代码块就表示一对大括号,但是定义的位置不同,功能就不同{逻辑}

代码块的分类:
局部代码块
构造代码块
静态代码块
同步代码块(多线程环节,讲解用于解决线程安全问题)

1.2 局部代码块
格式 : {逻辑}
位置 : 定义在方法中
作用 : 限制定义在局部代码块中的变量的作用范围

注意: 1) 定义在局部代码块之外的变量,那么在代码块中对变量做的操作,出了局部代码块,仍然生效;
2) 定义在局部代码块中的变量,一个是作用范围有限,如果局部代码块执行完毕,那么局部代码块中定义的变量就会变成垃圾,就会被回收掉,释放内存,节省内存空间.

代码
// 局部代码块 : {} 定义在方法中
public class DaiMaKuai1 {
public static void main(String[] args) {
int i = 10 ;

    // 局部代码块 : 限定定义在局部代码块中的变量的作用范围
	{
      System.out.println(i);// 10 
	  int j = 99 ;
	  System.out.println(j);// 99
	  i = 88 ;// 赋值
      System.out.println(i);// 88
	}
	System.out.println(i);// 88
	// System.out.println(j);// 报错,j的使用范围有限
}

}

1.3 构造代码块
格式 : {逻辑}
位置 : 类中方法外
作用 : 给成员变量进行赋值,如果多个构造方法都有一部分相同的逻辑,那么这部分相同的逻辑可以写在构造代码块中
执行机制 : 构造代码块,在创建对象的同时,JVM主动的调用执行,在构造方法之前执行,每次创建一个对象,构造代码块只执行一次

代码
//构造代码块
public class DaiMaKuai2 {
private String name ;

// 定义一个构造代码块
{
name = “张三”;
System.out.println(“构造方法被调用了”);
}

public DaiMaKuai2(){
//System.out.println(“构造方法被调用了”);
}

public DaiMaKuai2(String name){
//System.out.println(“构造方法被调用了”);
this.name = name;
}

public String getName(){
return name;
}

public static void main(String[] args) {
   DaiMaKuai2 d2 = new DaiMaKuai2("QQ");
   System.out.println(d2.getName());// QQ
}

}

1.4 静态代码块
格式 :
static {
逻辑
}
位置 : 类中方法外
作用 : 给静态的成员变量进行赋值,如果一个功能仅仅在类加载进内存时,只执行一次,那么这个部分功能可以写在静态代码块中
执行机制 : 当.class文件进入到内存中时,JVM会主动的调用一次静态的代码块,静态代码块在整个类的执行过程中,只执行一次,与创建多少对象无关

总结代码块的执行顺序:
静态代码块(只执行一次,与创建几次对象无关)----->构造代码块(每次创建对象执行一次)---->构造方法(每次创建对象执行一次) 局部代码块(方法进栈运行执行)

代码
// 静态代码块
public class DaiMaKuai3{
static String name ;
// 定义一个静态代码块
static{
name = “大美”;
System.out.println(“静态代码块执行了”);
}
// 构造代码块
{
System.out.println(“构造代码块begin”);
}

public DaiMaKuai3(){
   System.out.println("构造方法执行了");
}

public static void main(String[] args) {
	DaiMaKuai3 d3 = new DaiMaKuai3();
	DaiMaKuai3 dd3 = new DaiMaKuai3();
	System.out.println(DaiMaKuai3.name);// 大美
}

}

执行结果:
在这里插入图片描述

  1. 继承
    面向对象的一大特征
    2.1 继承的概述
    继承 : 指类与类之间的关系,子父关系
    关键字 : extends ,扩展,继承
    举例 : class A{} class B{} ----> class A extends B{}----> A类继承B类
    B类 : 叫做父类,超类,基类
    A类 : 叫做子类,派生类

2.2 继承发生的场景
继承,多个事物具有了一些共性,可以将共性向上抽取,抽取到一个父类中,其他类作为这个父类的子类存在,在父类中实现共性,子类中不需要再重复实现共性内容,可以直接使用父类中内容

一个Cat,猫类
class Cat{
睡觉;
吃饭;
抓老鼠;

}

一个类Dag,狗类
class Dog{
睡觉;
吃饭;
看家;
}

猫和狗都是属于动物,发现了动物具有共性,睡觉和吃饭,于是将睡觉和吃饭功能向上抽取,抽取到一个父类中,父类称为Animal,动物类

class Animal{
睡觉;
吃饭;
}

class Cat extends Animal{
抓老鼠;

}

class Dog extends Animal{
看家;
}

说明 : 请大家不要因为几个方法就去使用继承关系

代码
// 猫属于动物,因此猫继承动物类,作为动物类的子类
public class Cat extends Animal{

/*public void sleep(){
  System.out.println("睡觉");
}

public void eat(){

System.out.println("吃饭");
}*/

public void catchMouse(){
   System.out.println("猫抓老鼠");
}

}

// 狗也是动物的一种,因此狗继承动物类,作为动物类的子类
public class Dog extends Animal{
/*public void sleep(){
System.out.println(“睡觉”);
}
public void eat(){

System.out.println("吃饭");
}*/

public void lookHome(){
  System.out.println("狗能看家");
}

}

// Animal动物类 : 猫属于动物,狗也属于动物
public class Animal{
// 动物都需要吃饭和睡觉
public void sleep(){
System.out.println(“睡觉”);
}
public void eat(){
System.out.println(“吃饭”);
}
}

// 测试动物类
public class TestAnimal {
public static void main(String[] args) {
Cat c = new Cat();
c.sleep();// sleep方法来自于父类Animal中方法
c.eat();// eat来自父类Animal中的方法
c.catchMouse();// 猫类中自有方法

	Dog d = new Dog();
	d.sleep();
	d.eat();
	d.lookHome();
}

}

2.3 继承的优势和弊端
继承的优势:

  1. 提高代码的复用性
  2. 提高代码的可维护性(代码维护:代码修改的难易程度),表示代码修改时,方便,简易
  3. 继承为多态提供了前提

继承的弊端:

  1. 提高了类与类之间的耦合性
    耦合性 : 指类与类之间的关系,太紧密了
    举例,上面猫个狗,动物案例
    cat类和dog类中的sleep和eat方法,都是来自于Animal类中
    如果将Animal类删除了,Animal中所有子类所使用的sleep和eat都会受到影响

实际开发场景:
需要大家尽量做到类: 高内聚,低耦合
解释 : 类中的功能与其他外类的关联尽量不要太多,多数的功能能在类本身中实现

2.4 继承中的注意事项

  1. 父类中的私有成员(成员变量,方法),子类不能继承使用

原因 : private修饰的私有成员变量和方法,只能在本类中使用,子类并不是父类本身,也属于外类,因此私有无法被子类继承和使用

  1. 父类中的构造方法,不能被子类继承

原因 : 父类中的构造方法,与父类的名字一致;子类中的构造方法,与子类名字一致.弗雷德构造方法的名字与子类的名字不同,二构造方法的名字需要与类名一致,矛盾(父类构造不能被子类继承,但是可以被子类的构造方法调用)

代码
// 定义一个父类
public class Fu {
private int i = 9 ;

private void fun(){
   System.out.println("去玩");
}
public void work(){
 System.out.println("工作");
}	

}

// 定义一个子类,作为Fu类的子类
public class Zi extends Fu {

}

public class TestFu{
public static void main(String[] args) {
Zi z = new Zi();
// 子类不能继承和使用父类中的私有成员
//System.out.println(z.i);
// z.fun();
z.work();
}
}

2.5 成员变量在继承中的关系
子类可以无条件的继承父类中的所有非私有成员变量

  1. 子类可以使用父类中所有的非私有成员变量; 父类只能使用类中定义的成员变量,无法使用子类自己定义的成员变量
  2. 变量的访问具有就近原则,使用变量时,哪个变量离的最近,优先使用哪个变量(变量自己有不找别人)
  1. 如果方法中定义了局部变量,优先使用局部变量
  2. 如果没有局部变量,优先使用类中定义的成员变量
  3. 如果类中没有成员变量,优先使用父类中成员变量
  4. 父类中如果也没有成员变量,那么接着继续找父类的父类…直到找到Object类,仍然没有这个变量,报错

代码
// 定义一个父类
public class Fu {
// 在父类中定义成员变量 : 数据类型 变量名 = 变量值;
int a = 9 ;// 普通成员变量
private int b = 20;// 私有成员变量
static int c = 100;// 静态成员变量
}
// 定义一个子类,作为Fu类的子类
public class Zi extends Fu {
// Zi类可以从Fu类中继承到两个成员变量 int a = 9,c
int d = 200;
// 子类重新定义了变量a,与从父类继承来的变量a重名
int a = 900;
}

public class TestFu{
public static void main(String[] args) {
// 定义一个父类的对象
Fu f = new Fu();
// 父类不能使用子类自己定义的变量
//System.out.println(f.d);
// 定义一个子类的对象
Zi z = new Zi();
// 使用了子类重新定义的变量a,根据变量的就近访问原则,子类自己有的
// 变量,就不找父类调用
System.out.println(z.a);// 900
// 使用从父类继承而来的变量
System.out.println(z.c);// 100
// 使用从父类继承而来的变量
System.out.println(z.d);// 200
}
}

2.6 方法在继承中的关系
子类可以无条件的继承父类中的所有非私有的方法(构造方法除外)

  1. 子类中可以重写(Override)从父类中继承来的方法
  1. 什么叫方法的重写? 发生在子父类的继承关系中,子类将从父类继承来的方法重新定义一遍
  2. 方法重写,必须与方法名相同,参数列表相同,返回值相同
  3. 子类的方法权限,要大于等于父类方法权限
    public -----> 公共的,最大权限(到处都可以使用)
    默认权限----> 定义一个方法或者变量,没有给任何的修饰符,那么就是默认修饰,也是默认权限,使用default表示,但是default不能写出来,写出来报错
    private----> 私有的,最小权限(只能在本类中使用)

public -----> 默认----->private
4) 子类重写了父类的方法后,调用的就是子类的重写方法
5) 证明方法是重写方法,使用注解 @Override 写在方法之上,注解能帮你校验这个方式是不是重写的方法
6) 静态方法,只能继承使用,不能重写
因为静态方法,属于类;

代码
// 定义一个父类
public class Fu {

 //在父类中定义方法
 public void eat(){
    System.out.println("人需要吃饭");
 }

 public int getSum(int x , int y){
    System.out.println("x + y = " + (x+y));
    return x + y ;
 }

 private void sleep(){
   System.out.println("人需要睡觉");
 }

 public static void fun(){
   System.out.println("去玩");
 }

}

// 定义一个子类,作为Fu类的子类
public class Zi extends Fu {

// Zi类可以从Fu父类中继承到 eat , getSum ,fun
/*
  public int getSum(int x , int y){
    System.out.println("x + y = " + (x+y));
    return x + y ;
 }

*/
@Override
public int getSum(int x , int y){
   System.out.println("(x + y)*2 = " + (x+y)*2);
   return (x+y)*2;
}

/*
报错,不是方法重写
@Override
void fun1(){}*/

 // 静态方法不能重写,可以继承使用
 public static void fun(){
 
   System.out.println("去玩");
 }

}

public class TestFu{
public static void main(String[] args) {
// 继承之间的方法
// 调用从父类继承的方法eat
z.eat();
// 调用子类的重写方法
z.getSum(3,5);
// 调用从父类继承的方法fun
z.fun();
// 调用从父类继承的方法fun
Zi.fun();
}
}

说明 : 什么叫方法的重载(Overload)?什么叫做方法的重写(Override)?

重载: 在同一个类中,方法名相同,参数列表不同,与方法的返回值类型无关
重写: 在子父类的继承关系中,子类重写父类中的方法,要求 : 方法名,参数列表,返回值类型都必须与父类保持一致,重写的方法权限要大于等于父类权限

2.7 构造方法在继承中的关系
子类无法继承父类中的构造方法,但是子类的构造方法可以调用父类的构造方法

  1. 子类构造方法方法的第一行,默认存在(不写也存在)有一个表达式,super()
    super : 表示父类对象的引用
    super() : 表示调用父类的空参数构造方法
    子类构造方法第一行也可以手动的调用父类的有参数构造 super(实际参数);

代码
public class Fu1 {
String name ;
public Fu1(){
System.out.println(“我是父类构造”);
}
public Fu1(String name){

  this.name = name;
}

}

public class Zi1 extends Fu1{

public Zi1(){
// super()表示调用父类的空参数构造方法,默认存在
// 为什么 ? 构造方法是在new对象时,JVM虚拟机默认调用
// 如果需要调用父类的构造方法,父类的构造存在于父类中,于是
// 父类就需要进内存,父类优先于子类进内存,因为父类中的成员变量和方法
// 必须要先进内存,为了保证让子类继承使用
//super(); 默认
super(“大美”);// 可以手动在构造方法第一行调用父类的有参数构造
}

public static void main(String[] args) {
	Zi1 zi = new Zi1();// 我是父类构造
	System.out.println(zi.name);// 大美
}

}

2.8 super关键字的使用
super : 关键字,表示父类对象的引用

  1. 区分子类和父类重名的成员变量,加有super. 变量就是调用父类的成员变量(同理方法使用)
  2. 在子父类继承关系中,子类构造方法的第一行,默认调用super(); 也可以手动的添加其他的父类构造方法,super() ,必须写在构造方法第一行

this : 关键字,表示子类对象的引用

  1. 区分成员变量和局部变量的重名问题,加有this.关键字的变量就是成员变量
  2. 同一个类中,构造方法互相调用,使用this(实际参数);必须写在构造方法第一行

说明 : super() 或者 this() 二者只能选择一个

代码

public class Fu1 {
String name = “Fu”;
public Fu1(){
System.out.println(“我是父类构造”);
}
public Fu1(String name){
this.name = name;
}
}

public class Zi1 extends Fu1{
int age ;
String name = “Zi”;

public Zi1(){
//super(); 默认
}

public Zi1(int age){
// super() 或者 this() 二者只能选择一个
//super(“大美”);
this();
}

public void getName(){
//现在想要Fu结果,super----> new Fu()
System.out.println(super.name);//Fu
}

public static void main(String[] args) {
	Zi1 zi = new Zi1();// 我是父类构造
	zi.getName();//Fu

	Zi1 z = new Zi1(12);// 我是父类构造
	System.out.println(z.name);//zi
}

}

2.9 继承的特点

  1. 类与类之间只能单继承,一个子类只能有一个直接的父类
    举例 : class A{} class B{} class C{}
    class A extends B{}
    classA extends C{}
    在这里插入图片描述

  2. Java中支持多层继承
    class A{}
    class B{
    public void fun(){}
    }
    class C{
    public void eat(){}
    }

class A extends B{// A类是B类的子类
}

class B extends C{// B类是C类子类

}

说明 : B类是A类的父亲,C类是A类爷爷,
A类同时具有B类和C类的所有可继承的成员,A类即可以使用fun方法,也可以使用eat方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值