Java学习(七)类的补充

一、重写与重载的区别

重写(override) 重载(overload)
1.类 产生两个继承关系的类 子类重写父类中的方法 一个类中的一组方法
2.权限 子类可以大于等于父类 没有要求
3.特征 父类方法是final  子类不能重写 父类方法是static  子类不存在重写 父类方法是abstract  子类必须重写 子类是具体必须重写,否则子类是抽象类,可以不重写 没有要求
4.返回值 子类可以小于等于父类 没有要求
5.名字 子类与父类必须一致 一个类中的好多方法名必须一致
6.参数 子类与父类必须一致 每一个方法的参数必须不一致(个数 类型 顺序)
7.异常 如果父类方法抛出运行时异常,子类可以不予理会 如果父类方法抛出编译时异常,子类抛出异常的个数少于等于父类,类型小于等于父类 没有要求
8.方法体 子类的方法内容与父类不一致 每一个重载方法,执行过程不一致

二、Object类的方法

hashCode();//将对象在内存中的地址经过计算得到一个int整数
equals();//用来比较两个对象的内容 默认效果为==,可以重写
toString();//将对象变成一个String字符串
getClass();//获取对象对应类的类映射(反射)
wait();//线程进入挂起等待状态 存在重载
notify();//线程唤醒
notifyAll();//唤醒所有
finalize();//权限修饰符是protected 对象被垃圾回收的时候默认调用执行的方法
clone();//权限修饰符是protected 为了克隆对象

三、修饰符

  • 权限修饰符

    • public 公共的

    • protected 受保护的

    • 默认不写 默认的

    • private 私有的

权限修饰符可以修饰类本身和类中的成员

权限修饰符用来修饰类的时候只有两个可以用(public || 默认不写)如果加上public则要求类的名字与文件的名字必须一致,否则编译出错

权限修饰符都可以用来修饰类中的成员

本类中是否可以调用 同包可以调用 子类是否可以调用 任意位置
public
protected √ (通过子类的对象在子类的范围内部访问) ×
默认不写 × ×
private × × ×
  • 特征修饰符

    • 用abstract修饰的方法,只有方法的结构,没有方法执行体,叫做抽象方法

    • 用abstract修饰的类叫做抽象类

    • 抽象类不是必须有抽象方法

    • 普通类不允许含有抽象方法

    • 抽象类含有构造方法,但是不能通过构造方法直接创建对象,只能通过子类继承使用

    • 具体类不能直接继承抽象类,需要将父类的抽象方法具体化

    • 抽象类可以直接继承抽象类,不需要将父类的抽象方法具体化

    • 可以修饰属性、方法、块、类(内部类)

    • 静态元素在类加载时就初始化,创建的非常早

    • 静态元素存储在静态元素区中,每一个类有一个自己的区域,与别的类不冲突

    • 静态元素只加载一次,全部类对象及类本身共享

    • 由于在静态元素区加载的时候有可能没有加载对象,可以通过类名字直接访问

    • 静态元素区Garbage Collection(GC)无法管理回收,可以认为是常驻内存

    • 静态元素中不可以出现this或super关键字

    • 可以修饰变量、属性、方法、类本身

    • 变量=>修饰的变量如果没有赋值可以允许一次赋值

    • 属性=>修饰的属性由于自身有默认值,所以定义未赋值的属性将不能再次赋值

    • 方法=>修饰的方法不可更改,即不允许子类重写覆盖

    • 类=>修饰的类是最终的,不可更改(太监、无后)不能被继承,通常是一些定义好的工具

    • final 最终的 不可改变的

    • static 静态的

    • abstract 抽象的

      //抽象类
      public abstract class Animal{
         //定义抽象方法
         public abstract void eat();
      }
    • native 本地的

      在Java源代码中看到native就已经再也看不到后续代码,它后续会调用其他的编程语言去执行内存的操作

    • transient 瞬时的 短暂的

    • synchronized 同步的

    • volatile 不稳定的

四、类继承的执行顺序

  1. 加载父类

  2. 父类产生自己的静态空间(属性、方法、块、执行块)

  3. 执行父类静态块

  4. 加载子类

  5. 子类产生自己的静态空间(属性、方法、块、执行块)

  6. 执行子类静态块

  7. 开辟对象空间

  8. 加载父类的非静态成员(属性、方法、块、构造方法)

  9. 执行父类块

  10. 执行父类构造方法

  11. 加载子类的非静态成员(属性、方法、块、构造方法)

  12. 执行子类块

  13. 执行子类构造方法

  14. 将对象空间的地址引用给变量接收

五、动态参数列表

5.1动态参数列表

在JDK1.5版本之后,出现了一种叫动态参数列表的写法

  • 动态参数列表的写法,如:int...x

  • 参数的类型(如int)为固定的,但是参数个数是动态的,可以传多个值(从0个到n个都可以)。

  • 动态参数列表的方法不能与数组类型的方法构成重载,其本质是一样的,编译会报错如:testFun(int...x)testFun(int[])本质都是一维数组,不能同时存在

  • 虽然动态参数列表可以不传值,但是若是有一个同名字的空参数方法,在你不传值的时候还是会优先匹配空参数的方法

  • 动态参数列表在方法的参数中只能存在一份,而且必须放置在方法参数的列表,如:fun(int a,int...x)

public class Test {
   public void testFun(int...x){
       System.out.println("执行了动态参数列表方法");
       //因为动态参数列表本质为数组,所以可以通过数组遍历
       for(int i:x){
           System.out.println(i);
       }
   }
   public void testFun(){
       //虽然动态参数列表可以不传值,但是若是有一个同名字的空参数方法,在你不传值的时候还是会优先匹配空参数的方法
       System.out.println("执行了空参数的方法");
   }

   public static void main (String[] args){
       Test fun = new Test();
       //动态参数列表可以传多个相同类型的值
       fun.testFun(1,2,3,4,5,6);
       fun.testFun();
   }
}

执行结果:

执行了动态参数列表方法
1
2
3
4
5
6
执行了空参数的方法

六、多态

同一个对象,体现出来的多种不同形态(身份),将一种行为表现出不同的效果。

要想实现多态的效果需要现有继承关系

6.1多态的优点:

  1. 消除类型之间的耦合关系

  2. 可替换性

  3. 可扩充性

  4. 接口性

  5. 灵活性

  6. 简化性

6.2多态存在的条件:

  • 继承

  • 重写

  • 父类引用指向子类对象

如:Father p = new Child();

6.3多态的使用

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。

当使用多态方式调用属性时,使用的是父类中的属性,如果父类没有改属性,则会报错。

多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。

//创建一个父类
public class Animal{
   public void eat(){
       System.out.println("这是动物的吃饭");
   }
}
//子类继承父类
public class Cat extends Animal {
   public void eat(){
       System.out.println("这是猫的吃饭");
   }
   public void work(){
       System.out.println("猫能抓鱼");
   }
}
//使用
public class Test {
   public static void main(String[] args){
       //向上转型,此时以动物的身份来定义猫
       Animal a = new Cat();
       //执行为子类重写的结果
       a.eat();
       //无法调用子类的方法a.work();
 
       //判断前面引用与后面类型是否一致
       if(a instanceof Cat){
           //向下转型,将动物身份的猫转成猫的身份
           Cat b = (Cat)a;
       }
       b.eat();
       b.work();
   }
}

七、内部类

内部类是在Java中可以将一个类定义在另一个类的内部

内部类可以定义在类的内部(与类成员层次一致)

内部类可以定义在 方法/块内部(与类成员相差一个层次,方法的局部变量一个层次)

7.1成员内部类

将一个类直接定义在类的里面,作为成员,与属性或方法层次一致

成员内部类与正常的类一致,可以使用不同的修饰符来修饰

命名规则:外部类名$内部类名.class(Demo$InnerDemo.class)

成员内部的优点

  1. 省略了一个类的原文件

  2. 在成员内部类中可以访问外部所有的成员,包括私有的属性和方法

注意:若是在内部类中调用外部类成员,可以通过  外部类.this.外部类成员如:Demo.this.name

例子:

定义外部类内部类

package test;

public class Demo {
   private final String name = "这是正常类的属性";
   public void testDemo(){
       System.out.println("这是正常类中的方法");
   }

   //成员内部类
   public class InnerDemo{
       public void testInnerDemo(){
           //这里的name可以直接使用,若是内部类也含有name,可以通过Demo.this.name来调用外部类的属性/方法
           System.out.println("我是内部类的方法"  name);
           testDemo();
       }
   }
}

主方法

package test;
//导包,可以直接使用内部类
import test.Demo.InnerDemo;
public class TestMain {
   public static void main(String[] args){
       //因为内部类是属于外部类的,所以创建对象必须要外部类操作
       //先创建外部类对象
       Demo demo = new Demo();
       //用外部类来创建一个内部类
       InnerDemo innerDemo = demo.new InnerDemo();
       //调用内部类的方法
       innerDemo.testInnerDemo();
   }
}

执行结果:

我是内部类的方法这是正常类的属性
这是正常类中的方法

7.2局部内部类

将一个类定义在方法/块里面,作为成员的内部结构,与临时的局部变量一个层次

局部内部类类似一个局部变量,不能使用public/protected/private/static修饰,只能用abstract或final来修饰 。

局部内部类使用的变量只能是final修饰的

命名规则:外部类名$[序号]内部类名.class(Demo$1InnerTestDemo.class)

package test;

public class Demo {
   private final String name = "这是正常类的属性";
   public void testFun(){
       System.out.println("这是正常类中的方法");
   }
   public void testDemo(){
       final String s = "abc";
       //局部内部类
       class InnerTestDemo{
           //布局内部类
           public void show(){
               System.out.println(s);
           }
       }
   }
}

7.3匿名内部类*

含有:成员匿名内部类/局部匿名内部类

开发中为了省略一个文件,常见以下写法:

public interface Demo {
   public void test();
}
public class TestMain {
   public static void main(String[] args){
       //创建一个匿名内部类
       Demo demo = new Demo(){
           public void test(){
           }
       };
}
}

匿名内部类很特殊,只有类体,没有类的所有结构:修饰符、名字、继承、实现,也没有类的构造方法

7.4静态内部类

只含有:成员内部类

不需要外部类对象,通过正常的方式直接创建内部类

package test;

public class Demo {
   //静态成员内部类
   public static class InnerDemo{
       //静态元素不能访问非静态成员(自己类和外部类都不行)
   }
}
package test;
//导包,可以直接使用内部类
import test.Demo.InnerDemo;
public class TestMain {
   public static void main(String[] args){
       //可以直接new静态成员内部类
       InnerDemo innerDemo = new InnerDemo();
   }
}
夜河资源网提供的所有内容仅供学习与交流。通过使用本站内容随之而来的风险以及法律责任与本站无关,所承担的法律责任由使用者承担。
一、如果您发现本站侵害了相关版权,请附上本站侵权链接和您的版权证明一并发送至邮箱:yehes#qq.com(#替换为@)我们将会在五天内处理并断开该文章下载地址。
二、本站所有资源来自互联网整理收集,全部内容采用撰写共用版权协议,要求署名、非商业用途和相同方式共享,如转载请也遵循撰写共用协议。
三、根据署名-非商业性使用-相同方式共享 (by-nc-sa) 许可协议规定,只要他人在以原作品为基础创作的新作品上适用同一类型的许可协议,并且在新作品发布的显著位置,注明原作者的姓名、来源及其采用的知识共享协议,与该作品在本网站的原发地址建立链接,他人就可基于非商业目的对原作品重新编排、修改、节选或者本人的作品为基础进行创作和发布。
四、基于原作品创作的所有新作品都要适用同一类型的许可协议,因此适用该项协议, 对任何以他人原作为基础创作的作品自然同样都不得商业性用途。
五、根据二〇〇二年一月一日《计算机软件保护条例》规定:为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可不经软件著作权人许可,无需向其支付报酬!
六、鉴此,也望大家按此说明转载和分享资源!本站提供的所有信息、教程、软件版权归原公司所有,仅供日常使用,不得用于任何商业用途,下载试用后请24小时内删除,因下载本站资源造成的损失,全部由使用者本人承担!