java-面向对象高阶

本文详细介绍了Java的面向对象特性,包括继承、抽象类、多态、接口、final关键字等概念。阐述了继承的格式和限制,super的使用,方法重写与重载的区别,以及final修饰的属性和方法。探讨了抽象类与抽象方法的规则,接口的定义,多态的体现,并讲解了Object类、==与equals的区别。此外,还提到了字符串转换、可变参数和递归等主题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

继承
继承格式
class 父类{
}
class 子类 extends 父类{
    
}
  • 继承是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法, 或子类从弗雷继承方法,使得子类具有父类相同的行为
  • 继承限制:
    • java中只有单继承,多重继承 (继承爷爷的性质),没有多继承
super:
  • 通过super,可以访问父类的构造方法

    • 在继承时,子类默认使用父类无参的构造方法

    • 如果父类没有无参的构造方法则需要使用super()调用

      class 父类{
      }
      class 子类 extends 父类{

      }

  • 通过super,可以访问父类的属性

  • 通过super,可以访问父类的方法

方法重写
  • 参数列表必须完全和被重写的方法相同
  • 返回值类型必须完全与被重写的方法的返回值类型一直
  • 访问权限不能比父类中被重写的方法的访问权限低,
  • 父类的成员方法只能被他的子类重写
  • 声明为static和private的方法不能被重写,但是能够再次声明
    class Work{
    	public void say() {
    		System.out.println("I gnna work");
    	}
    	
    }
    class myWork extends Work{
    	public void say() {
    		System.out.println("I gnna study");
    	}
    }


方法重写 和重载的区别
  • 发生位置
    • 重载:一个类中
    • 重写:父子类中
  • 参数列表限制
    • 重载:必须不同、
    • 重写:类型、数目 必须相同
  • 访问权限:
    • 重载:与访问权限无关(各种重载的方法随意设置权限)
    • 重写:子类的访问权限必须 不小于 父类的访问权限
  • 返回值:
    • 重载:与返回值类型无关
    • 重写:返回值类型必须一致
  • 异常处理:
    • 重载:与异常处理无关
    • 重写:异常范围可以更小,但是不能抛出新的异常
final关键字
  • final用于修饰属性 变量
    • 变量成为常量,无法再对其赋值
    • 常量的命名规范 由一个或多个单词形成,单词与单词之间必须使用下划线隔开,单词中所有的字母大写
    • final修饰的局部变量,只能赋值一次(可先声明后赋值)
    • final修饰成员属性,必须在声明的时候赋值
  • 用于修饰类
    • final修饰的类,不能被继承
  • 用于修饰方法
    • final修饰的方法不能被子类重写
抽象类
	抽象类必须使用 abstract class 声明
    一个抽象类中可以没有抽象方法。抽象方法必须写在抽象类或接口中
     	抽象类中可以有一些具体实现的方法
    格式:
        abstract class 类名{  //抽象类
        }
抽象方法:
  • 只声明未实现的方法称为抽象方法( 未实现指的是:没有{}方法体)

  • 抽象方法必须使用abstrct关键字声明

    abstract class 类名{
    public abstract void 方法名(); // abstract 返回值类型 必须有
    }

在抽象类使用的规则:
  • 抽象类本身不能进行实例化的操作,即不能使用 new关键字来完成
  • 一个抽象类必须被子类所继承,被继承的子类如果不是抽象类,则必须重写抽象类中的全部抽象方法
  • 抽象类不能使用final声明
  • 抽象类可以有构造方法,而且子类对象实例化时候的流程与普通类继承是一样的,都是先调用父类中的构造方法(默认无参),之后再调用子类知己的构造方法。
抽象类和普通类的区别
  • 抽象类只能使用 public 或 procted 修饰(如果父类是 private修饰,那么子类无法继承,也无法实现其抽象方法),缺省 默认为 public
接口
  • 如果一个类中全部的方法都是抽象方法,全部的属性 都是全局常量,那么此时就可以将这个类定义成接口

    interface 接口名称{
    全局常量;
    抽象方法;
    }

  • 接口中可以省略 public abstract

多态
  • 就是对象的多种表现形式
多态的体现:
  • 子类就是父类的一种形态
  • 方法的重载 和 重写 就是多态的一种, 只不过是方法的多态 (相同方法名的多种形体)
    • 重载:一个类中方法的多态性体现
    • 重写: 子父类中方法的多态性体现
Object 类
  • 如果在创建类的时候没有声明要继承的类,那么java就默认他继承Object类
  • Object 的toString类
    • 类Object 的toString方法返回一个字符串,该字符串由对象为实例的类的名称,符号字符“@”以及对象的哈希码的无符号十六进制表示形式组成。
    • 换句话说,此方法返回一个 值等于 getClass().getName() + “@”+ Integer.toHexString(hashCode())
    • 当我们使用Syso打印对象的时候,就是在调用toString()方法,可以查看println底层源码
    • 我们可以重写 toString方法

== 与equals
  • ==

    • 用于基本数据类型的比较
    • 判断引用的是否指向同一块内存地址
  • object 底层源码 的 equals 方法,是用的 == ,所以如果想实现比较其内容的话,要根据需求重写 equals方法
    public boolean equals(Object obj) {
    return (this == obj);
    }

  • equals,重写时需要满足一下条件(理解即可)

    • 自反性 :对于任何非空的参考值x , x.equals(x)应该返回true 。
    • 它是对称的 :对于任何非空引用值x和y , x.equals(y)应该返回true当且仅当y.equals(x)回报true 。
    • 传递性 :对于任何非空引用值x , y和z ,如果x.equals(y)回报true个y.equals(z)回报true ,然后x.equals(z)应该返回true 。
    • 它是一致的 :对于任何非空引用值x和y ,多次调用x.equals(y)始终返回true或始终返回false ,前提是未修改对象上的equals比较中使用的信息。
    • 对于任何非空的参考值x , x.equals(null)应该返回false 。
  • 快捷键生成equals 方法 shift+ alt+s 选择:Generate hashCode() and equals

    //重写equals代码	
    public boolean  equals(Object o) {
    		if(this == o) { //判断两者内存地址是否一致
    			return true;
    		}
    		if(o==null) {  //判断 o 对象 是否为 空
    			return false;  
    		}
    		if( (o instanceof Persons) ){ 
    			Persons p2 = (Persons)o;
    			if(this.name.equals(p2.name) && this.age == p2.age) {
    				return true;
    			}
    		}
    		return false;
    	}
    
  • String 作为一个基本数据类型来使用
    String s1 = “java”;
    String s2 = “java”;

        System.out.println(s1==s2);            //true
        System.out.println(s1.equals(s2));    //true
    
    why?
        在此处程序员把String 作为一个基本的数据类型来使用
        如果String缓冲池内不存在与其指定值相同的String对象,那么此时虚拟机将为此创建新的String对象,并存放在String缓冲池内。
    	如果String缓冲池内存在与其指定值相同的String对象,那么此时虚拟机将不为此创建新的String对象,而直接返回已存在的String对象的引用。
    

    JVM把内存划分成两种:一种是栈内存,一种是堆内存。
      ①在函数中定义的一些基本类型的变量和对象的引用变量(变量名)都在函数的栈内存中分配。
      ②当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用

内部类:(不重要)
  • 在java中,可以将一个类定义在另一个类里面或者一个方法里边
  • 内部类一般包括:
    • 成员内部类:

      • 成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)
      • 注意:当成员内部类拥有和外部类同名的成员变量或者方法是,会发生隐藏现象,默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以 外部类.this.成员变量 外部类.this.成员方法
      • 外部类使用成员内部类
        Outter outter = new Outter();
        Outter.Inner inner = outter.new Inner();
    • 局部内部类

      • 是定义在一个方法或者一个作用域里面的类,他和成员内部类的区别在于
      • 局部内部类就像是 方法里面的一个局部变量,不能有public protected、private 以及static修饰
    • 匿名内部类:没有名字,在创建时只能用一次

      • 匿名内部类的使用规范
        • 使用匿名内部类时,我们必须继承一个类或者一个借口,但是两者不可兼得,同时也只能继承一个类或者接口
        • 匿名内部类中不能有构造方法
        • 匿名内部类为局部内部类的一种, so局部内部类的限制同样对匿名内部类生效
        • 匿名内部类不能是抽象的,他必须要实现接口的所有抽象方法
        • 只能访问final修饰的局部变量 内部类会被单独编译成一个字节码文件,为了保证内部类 和 外边的值一致,限制了变量的值不可更改
        public class Demo1 {
         
        	public static void main(String[] args) {
        		
        		// 创建了一个Human 接口的实现类,并new了一个对象
        //		匿名内部类
        		Human p = new Human() { 
        			public void say() {
        				System.out.println("匿名内部类");
        			}
        		};
        		haha(p);
        	}
        	
        	public static void haha(Human p) {
        		
        	}
        }
    
  • 静态内部类
包装类:

在Java中有一个设计的原则“一切皆对象”,那么这样一来Java中的一些基本的数据类型,就完全不符合于这种设计思 想,因为Java中的八种基本数据类型并不是引用数据类型,所以Java中为了解决这样的问题,引入了八种基本数据类型 的包装类

|序号| 基本数据类型| 包装类 

1  int  Integer 

2  char  Character 

3  float  Float 

4  double  Double 

5  boolean  Boolean 

6  byte  Byte 

7  short  Short 

8  long  Long
  • 8种包装类,可以将基本数据类型按照类的形式进行操作
  • 可分为两大种类型:(Ctrl+T 可以查看类的结构)
    • Number: Interage \ Short \ Long \ Double \ Float \ Byte 都是Number的子类
    • Object:Character、Boolean 都是Object的直接子类

    //		包装类的学习:
    //		手动装箱
    		Integer num = new Integer(200); // 删除线,指此操作已经过时
    //		手动拆箱
    		int a = num.intValue();
    		System.out.println("包装类拆箱结果为:"+a);
    		
    //		自动装箱
    		Integer num1 = 200;
    //		自动拆箱
    		int b = num1;
字符串转换:
  • 使用包装类可以讲一个字符串变为指定的基本数据类型,一般在接收输入数据时使用较多
    System.out.println(“请输入内容”);
    String text = scanner.next();
    System.out.println(“字符拼接”+text+1); //string + int 实现的效果是字符串的拼接

    		int num = Integer.parseInt(text);    //此处 num 为int型
    		System.out.println("?:"+num+1);     //因为前边有 字符串类型,所以会自动将num、1转换成string类型
    		System.out.println(num+1);   
    
可变参数:
  • 一个方法中定完了参数,则在带哦用时必须传入与其一一对应的参数,但是在jdk1.5之后提供了新的功能,可以根据需要自动传入任意个数的参数

  • 注意:可变参数只能出现在参数列表的最后

      public static int sum(int...nums) {
      	int n =0;
      	for(int i=0;i<nums.length;i++) {
      		n+=nums[i];
      	}
      	return n;
      }
    
      	System.out.println(sum(1));
      	System.out.println(sum(1,2));
    
递归
  • 递归在数学与科学计算机科学中,是种方法的定义中使用方法自身。也就是说,递归算法是一种直接或者间接
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只小白小小白小白鼠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值