类和对象续

news2024/11/26 2:51:35

目录

自定义包

包的访问权限控制

常见的包

Static成员

静态成员变量

静态成员方法

代码块 

构造块

静态块

重写 

继承

继承是啥?

父类成员访问

子类中访问父类成员变量

两者不同名

两者同名

子类中访问父类对的成员方法

super

子类构造方法

this和super

 代码块再解读

protected关键字

继承方式

 多态

向上转型:把子类所引用的对象给到父类

再说重写 

向下转型

多态的好处


自定义包

选中src右键选择new-->package,创建名字

创建好名字后在下方新建一个testwww

建完的界面就是这样滴

包的访问权限控制

在自定义包下创建新程序TestOne和一个新的包demo,在demo下再创建一个新程序TestTwo

//TestOne
package com.bitejiuyeke.www;

public class TestOne {
    String name = "zhangsan";

    public static void main(String[] args) {

    }
}

因为封装在TestTwo中无法引用TestOne中的变量。

常见的包

1. java.lang: 系统常用基础类 (String Object), 此包从 JDK1.1 后自动导入。
2. java.lang.reflflect:java 反射编程包 ;
3. java.net: 进行网络编程开发包。
4. java.sql: 进行数据库开发的支持包。
5. java.util: java 提供的工具程序包。 ( 集合类等 ) 非常重要
6. java.io:I/O 编程开发包。

Static成员

静态成员变量

 假设学生都在一个教室上课

我们就把classroom拿出来当成静态类

public static String classroom;

特性:

1. 不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中
2. 既可以通过对象访问,也可以通过类名访问,但一般更推荐使用类名访问
3. 类变量存储在方法区当中
4. 生命周期伴随类的一生 ( 即:随类的加载而创建,随类的卸载而销毁 )

静态成员方法

public class Student{
    // ...
    private static String classRoom = "Bit306";
    // ...
    public static String getClassRoom(){
        return classRoom;
    }
}
public class TestStudent {
    public static void main(String[] args) {
        System.out.println(Student.getClassRoom());
    }
}

 特性

1. 不属于某个具体的对象,是类方法
2. 可以通过对象调用,也可以通过类名 . 静态方法名 (...) 方式调用,更推荐使用后者
3. 不能在静态方法中访问任何非静态成员变量

初始化

1.就地初始化

直接赋值

2.代码块初始化

代码块 

构造块

静态块

结论:

静态代码块先执行

然后执行构造代码块

在实行对应的构造方法

静态的只执行1次  

同步代码块

这些静态代码块可以合并成一个代码块


重写 

    public static void main(String[] args) {
        Student student = new Student("张三",10);
        System.out.println(student);
    }

打印结果是

为什么会打印粗这样的结果呢?

我们control点进去println底层

valueOf底层

toString底层

我们完全可以再自己代码中重新写一个toString方法,这样系统不会调用底层的代码,而会先考虑你写的新方法

点击鼠标右键选择generate,点进去toString,系统帮你生成一段新的打印代码,利用这段代码就可以正常打印了

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
        //return "lalala"//这样就可以打印lalala
    }

这种方法叫做重写


    //方法1    
    public static int add(int a,int b) {
        return a+b;
    }
    //方法2
    public static int add(int a,int b,int c) {
        return a+b+c;
    }
    //方法3
    public static int add(int[] array) {
        int ret = 0;
        for (int x: array) {
            ret += x;
        }
        return ret;
    }

    public static void main(String[] args) {
        int[] array = {1, 2, 3, 4, 5};
        System.out.println(add(array));
        System.out.println(add(new int[]{1, 3, 4, 5, 6}));//匿名对象
    }

方法3还有一个更🐂的重写方法

    /**
     * ...可变参数
     * @param array
     * @return
     */
    
    public static int add(int... array){
        int ret = 0;
        for (int x: array) {
            ret += x;
        }
        return ret;
    }

继承

继承是啥?

这两个类都有相同的eat方法

每个动物都有这几个共同的特点,把这些类的共性进行抽取,放到特定的类中,从而达到代码的复用效果。这种类就叫继承

抽取新建共性类Animal

class Animal{//抽取出来的类
    public String name;
    public int age;
    public void eat(){
        System.out.println(this.name + "正在吃饭");
    }
}

 

这里的Dog跟Animal是is-a的关系,Dog称为子类或者派生类,Animal称为父类或者基类或者超类

extends是拓展的意思,也就是继承


在Animal类中,访问修饰限定符只能决定访问权限,不能决定能不能被继承

所以在后面的类中,虽然name不能被访问,但是是可以继承的,提供一个get方法就能访问


父类成员访问

子类中访问父类成员变量

两者不同名
class Base{
    public int a;
    public int b;
}
class Derived extends Base{
    public int c;
    public void method(){
        a = 1;
        b = 2;
        c = 3;
    }
}
public class Test2{
    public static void main(String[] args) {
        Derived derived = new Derived();
    }
}

 这样的访问是不受限制的


两者同名
class Base{
    public int a = 9;
    public int b = 99;
}
class Derived extends Base{
    public int a = 88;
    public void method(){
        System.out.println("a: " + a);
        System.out.println("b: " + b);
    }
}

打印结果: 

当父类和子类的成员变量同名时,在子类当中使用时,优先打印子类的成员变量

总结:成员变量访问遵循就近原则,自己有优先自己的,没有再从父类中找


子类中访问父类对的成员方法

跟上面的成员变量访问差不多

通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到
则访问,否则编译报错。
通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同 ( 重载 ) ,根据调用
方法适传递的参数选择合适的方法访问,如果没有则报错;

如果子类中存在和父类相同的成员时,怎么再子类中访问父类相同名称的成员呢?

super

super在子类方法中访问父类的成员变量和方法


子类构造方法

回到刚才的Animal类中,构造Animal类的构造方法

Dog报错了,因为子类没有初始化父类成员,子类在构造完之前,一定要帮助父类进行初始化

圆圆和10就是对name和age的初始化

或者这样写(generate-->constructor)

    public Dog(String name, int age){
        super(name, age);
    }

super()调用父类的构造方法,帮助初始化子类从父类继承过来的成员,并不会生成父类对象

this和super

相同点
1. 都是 Java 中的关键字
2. 只能在类的非静态(main不行)方法中使用,用来访问非静态成员方法和字段
3. 在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在
不同点
1. this 是当前对象的引用,当前对象即调用实例方法的对象, super相当于是子类对象中从父类继承下来部分成员的引用
2. 在非静态成员方法中, this 用来访问本类的方法和属性, super 用来访问父类继承下来的方法和属性
3. 在构造方法中: this(...) 用于调用本类构造方法, super(...) 用于调用父类构造方法,两种调用不能同时在构造方法中出现
4. 构造方法中一定会存在 super(...) 的调用,用户没有写编译器也会增加,但是 this(...) 用户不写则没有

 代码块再解读

class Animal{//抽取出来的类
    public String name;
    public int age;
    public void eat(){
        System.out.println(this.name + "正在吃饭");
    }

    static {
        System.out.println("Animal::static{静态}");
    }
    {
        System.out.println("Animal::{实例}");
    }
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("Animal(String name, int age)");
    }
}
//拓展
class Dog extends Animal{//狗继承了Animal
    static{
        System.out.println("Dog::static{静态}");
    }
    {
        System.out.println("Dog::{实例}");
    }
    public Dog(String name, int age){
        super(name, age);
        System.out.println("Dog(String name, int age)");
    }
    public void bark() {
        System.out.println(this.name+ " 正在旺旺叫!");
    }
}
class Test{
    public static void main(String[] args) {
        Dog dog = new Dog("圆圆",10);
    }
}

 打印结果是什么呢?

两个静态优先执行,父类再执行,子类最后执行

再多两行代码

        System.out.println("================");
        Dog dog2 = new Dog("圆圆",10);

静态的就不执行了


protected关键字

package demo;

public class Test3 {
    protected int a = 19999;
}

为什么不能打印a,就算调用super也不行呢?

因为demo2里面的Test既不是Test3的子类,又与Test3处于不同包

看回之前的那张表,这张表在我一篇博客提过

JAVA类和对象_cx努力编程中的博客-CSDN博客

此时protected正好满足第四类的限制

这个表格的前提继承的父类是由public修饰的

注意:这里的public不能替换成private或者protected


继承方式

1.现在有一需求:当集成到某个层次上之后我们不再继承了

final是密封类,表示当前不能继承了。

final的另一个用法。下面的a只能初始化一次,成为了常量,恒等于199,再次初始化会报错。

        final int a = 199;
        a = 20;//err
        System.out.println(a);

final代表不可变 e.g String

2.组合(has-a/a part of关系)

class Tire{
// ...
}
// 发动机类
class Engine{
// ...
}
// 车载系统类
class VehicleSystem{
// ...
}
class Car{
    private Tire tire; // 可以复用轮胎中的属性和方法
    private Engine engine; // 可以复用发动机中的属性和方法
    private VehicleSystem vs; // 可以复用车载系统中的属性和方法
// ...
}
// 奔驰是汽车
class Benz extend Car{
// 将汽车中包含的:轮胎、发送机、车载系统全部继承下来
}

 多态

同一个人对待不同人表现出不一样的形态,这可以理解为最基本的多态

条件:

1.继承关系上-->向上转型

2.子类和父类有同名的覆盖/重写方法

3.通过父类对象的引用去调用这个重写的方法


向上转型:把子类所引用的对象给到父类

常见的可以发生线上转型的三个时机 

//1.直接赋值
        /*Dog dog = new Dog("圆圆",10);
        animal这个引用指向dog这个引用所指向的对象;
        Animal animal = dog;*/
        Animal animal = new Dog("圆圆",10);
//2.方法的参数,传参的时候进行向上转型
    public static void func1(Animal animal){
        
    }
    public static void main(String[] args) {
        Dog dog = new Dog("圆圆",10);
        func1(dog);
    }
//3.返回值向上转型
    public static Animal func2(){
        Dog dog = new Dog("圆圆",10);
        return dog;
    }

再说重写 

当我们在Dog类中加入eat()方法

    public void eat(){
        System.out.println(this.name + "正在吃狗粮!");
    }
//Animal  
        public void eat(){
        System.out.println(this.name + "正在吃饭");
    }
//Test
        public static void main(String[] args) {
        Animal animal = new Dog("圆圆",10);
        animal.eat();
    }

打印结果是

这两个eat方法满足方法返回值一样,方法名一样,方法的参数列表一样 

继承关系上,这两个方法关系是重写

但是在调用的时候忽然变成了调用子类的eat,这个过程叫做动态绑定

子类如果有eat方法那就调用子类的,子类没有就调用父类的

程序在编译的时候,确实调用的是Animal的eat

程序在运行时,调用了Dog的eat方法,是在这个时候才绑定方法(区分静态绑定)


静态绑定是什么呢?

像这种在编译的时候已经确定了调用谁,就是静态绑定


我们在写重写时,一般要在上面加一个注释,这个注释可以帮助你避免一些错误

 实现重写:

1.最基本的返回值参数列表,方法名必须是一样的

2.被重写的方法的访问修饰限定符在子类中要大于等于父类的

访问修饰限定符大小关系:private>default>protected>public

3.被private,static,final修饰的方法和构造方法是不能被重写的

4.被重写的方法返回值类型可以不同,但必须有父子关系,比如:

这种叫做协变类型 

重写快捷方法,鼠标右键选generate,选择要重写的方法


    public static void eatFun(Animal animal){
        animal.eat();
    }

    public static void main(String[] args) {
        Dog dog = new Dog("圆圆", 19);
        eatFun(dog);
        
        Cat cat = new Cat("咪咪", 1);
        eatFun(cat);
    }
//圆圆正在吃狗粮!
//咪咪 正在吃猫粮!

当父类引用的子类对象不一样的时候,调用这个重写的方法,所表现出来的行为是不一样的!我们把这种思想叫做多态

向下转型

我们知道dog和cat都属于animal,但是反过来,animal就一定是dog吗,这里拿一个大类去调用一个小类的方法明显不可能

我们需要强制转换类型,这也叫做向下转型,但是这种转型非常不安全

当我们使用cat类的时候就发现类型转换异常,就算强行转换也无济于事

那我如何避免用错类来向下转型呢?我们可以用instanceof

        if (animal instanceof Cat) {
            Cat cat = (Cat) animal;

            cat.miaomiao();
        }else{
            System.out.println("好吧!");
        }

多态的好处

class Rect extends Shape{
    
    @Override
    public void draw(){
        System.out.println("矩形");
    }
}

class  Triangle extends Shape{
    @Override
    public void draw() {
        System.out.println("🔺!");
    }
}

class Cycle extends Shape{
    @Override
    public void draw() {
        System.out.println("圆形!");
    }
}

public class Test {
    public static void main(String[] args) {
        Cycle cycle = new Cycle();
        Rect rect = new Rect();
        Triangle triangle = new Triangle();
        String[] strings = {"cycle","rect","cycle","rect","triangle"};
        for(String x :strings){
            if(x.equals("cycle")){
                cycle.draw();
            }else if (x.equals("rect")){
                rect.draw();
            }else if (x.equals("triangle")){
                triangle.draw();
            }
        }
    }
}

如果有大量的条件和循环语句,这种代码拥有圈复杂度,我们可以用多态来降低这种复杂度

    public static void drawMap(Shape shape){
        shape.draw();
    }

    public static void main(String[] args) {

        Shape[] shapes = {new Cycle(), new Rect(), new Cycle(), new Rect(), new Triangle()};
        for(Shape shape: shapes){
            shape.draw();
        }

    }

这段代码的扩展能力非常强,在上方添加一个类下面就能给你画出来

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1005310.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

浮点型数据在内存中是如何存储的

文章目录 浮点型变量的存储规则:浮点数怎么转化为二进制浮点型数据在内存中的存储E不全为0或不全为1E为全0E为全1 浮点型变量的存储规则: 根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下…

java判断两个时间是不是同一天的方法、Java中判断是否是当天时间

文章底部有个人公众号:热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享? 踩过的坑没必要让别人在再踩,自己复盘也能加深记忆。利己利人、所谓双赢。 热爱技术的小郑 前言 开发中会遇到这样一…

简简单单教你如何用C语言实现获取当前所有可用网口!

一、获取本机所有可用网卡名 原理: 在 Linux 系统中,/proc 目录是一个位于内存中的伪文件系统。 /proc目录是内核提供给我们的查询中心,通过查询该目录下的文件内容,可以获取到有关系统硬件及当前运行进程的信息,如…

【C++基础】左值引用、右值引用、move、forward

本文参考:右值引用 | 爱编程的大丙 转移和完美转发 | 爱编程的大丙 左值、右值、左值引用、右值引用 左值 是指存储在内存中、有明确存储地址(可取地址)的数据; 右值 是指可以提供数据值的数据(不可取地址&#x…

阶乘的素因数分解

一、题目 整除问题_牛客题霸_牛客网 (nowcoder.com) 二、普通数字的素因数分解 假如对n进行素因数分解。先利用素数筛法筛选出0~n范围内的全部素数。然后依次遍历这些素数,用n除以这些素数,直至无法整除。然后接着用下一个素数作为除数,直到n…

重庆OV证书和EV证书有什么区别

SSL数字证书按照保护的域名数量和类型可以分为单域名SSL证书、多域名SSL证书和通配符SSL证书三种,按照验证方式可以将SSL数字证书分为DV基础型SSL证书、OV企业型SSL证书和EV增强型SSL证书三种。今天就随SSL盾小编了解OV证书和EV证书的区别。 1.OV企业型SSL证书由CA…

Linux学习总结

Linux学习目标: Linux操作系统介绍与安装。 Linux常用命令。 Linux常用软件安装。 Linux网络。 防火墙。 Shell编程等。 *******************************LinuxOS介绍与安装************************************ Linux OS介绍与安装 Linux是什么&#xff…

C# 去除utf-8 BOM头

static void Main(string[] args) {var a1 Encoding.UTF8.GetBytes("<");var a2 Encoding.UTF8.GetBytes("&#xfeff;<");Console.WriteLine("去除utf-8 bom之前");Console.WriteLine(Encoding.UTF8.GetString(a1));Console.WriteLine(…

黑马 小兔鲜儿 uniapp 小程序开发- 推荐模块- day03

黑马 小兔鲜儿 uniapp 小程序开发- 02首页模块_软工菜鸡的博客-CSDN博客 小兔鲜儿 - 推荐模块- day03 主要实现 Tabs 交互、多 Tabs 列表分页加载数据。 动态获取数据 参考效果 推荐模块的布局结构是相同的&#xff0c;因此我们可以复用相同的页面及交互&#xff0c;只是所…

轻松打造自己的ChatGPT应用,AI应用,源码附赠

这里写自定义目录标题 前言简介 前言 大家好&#xff0c;我是静幽水&#xff0c;目前是一名大厂全栈工程师&#xff0c;练习时长两年&#xff0c;擅长Java后端&#xff0c;Vue前端&#xff0c;小程序编程&#xff0c;Python编程&#xff0c;ChatGPT 提示词等技术。现在正在系统…

建筑模板木模好还是钢模好

在建筑施工中&#xff0c;模板是一项关键的工程&#xff0c;对于建筑结构的质量和施工效率起着重要作用。在选择模板材料时&#xff0c;木模和钢模都是常见的选择。本文将比较木模和钢模的优缺点&#xff0c;以帮助您做出明智的选择。 正文&#xff1a;一、木模&#xff1a;传统…

信创国产化解决方案

近年来&#xff0c;随着信息技术的飞速发展&#xff0c;信创产业成为国家发展的重要战略之一。2018年以来我国将信创纳入国家战略&#xff0c;提出了“28”发展体系&#xff0c;随后扩展至更多行业&#xff0c;演变为“28N”应用体系。2023年中国信创产业逐步走向应用落地阶段。…

sql函数实现模糊精确匹配

sql函数实现模糊精确匹配 例如&#xff1a; 查询的时候匹配[‘1’] 就只匹配1的 &#xff0c;而不是15的也会模糊查询进去 slq函数如下&#xff1a; CREATE OR REPLACE FUNCTION does_string_array_intersect ( target_string TEXT, input_strings TEXT [] ) RETURNS BOOLEA…

单元格法求解多边形最大内接矩形问题【思路讲解+java实现】

问题描述 给定一个多边形的点集&#xff0c;希望找出多边形内部面积最大的矩形。该问题可能出现在&#xff0c;从一个多边形废料上面切割出一个最大的矩形&#xff0c;该矩形可以重复利用&#xff0c;解决该问题可以节约原材料&#xff0c;降低企业运作成本 问题解决方案 本…

解决Selenium元素拖拽不生效Bug

前几天在使用Selenium进行元素拖拽操作时&#xff0c;发现Selenium自带的元素拖拽方法&#xff08;dragAndDrop()&#xff09;不生效&#xff0c;网上的回答也是五花八门&#xff0c;比较混乱&#xff0c;尝试了以下几种方法均无法解决。 方案1&#xff1a;通过dragAndDrop()方…

群晖NAS如何在内网部署HTTPS服务让浏览器信任证书

前言 最近在折腾内部部署Web服务。通过Vue实现一个H5的内部的管理服务。但在实际部署过程中由于种种原因&#xff0c;必须部署成Https服务。但在部署成Https服务后&#xff0c;由于没有HTTPS证书&#xff0c;每次进入页面都会被浏览器拦截。使用起来非常不便。于是开始各种Goo…

显示器显示的画面突然偏红色如何解决

显示器显示的画面突然偏红色如何解决 1. 概述2. 解决方法结束语 1. 概述 显示器显示的画面突然偏红色 &#xff0c;使用向日葵远程电脑&#xff0c;看到的画面是正常的&#xff0c;但是显示器上的画面确还是骗红的&#xff0c;这时候就需要看一下是不是开启了系统也夜间模式&a…

Linux之使用LAMP搭建私有云存储

目录 Linux之使用LAMP搭建私有云存储 恢复快照&#xff0c;关闭安全软件 搭建LAMP环境 下载安装依赖包 下载nextcloud软件 解压nextcloud 设置nextcloud安装命令权限 数据库配置 设置数据库 重启数据库 配置httpd 重启httpd服务 安装 打开浏览器后输入服务器IP地址…

LeetCode(力扣)1005. K 次取反后最大化的数组和Python

LeetCode1005. K 次取反后最大化的数组和 题目链接代码 题目链接 https://leetcode.cn/problems/maximize-sum-of-array-after-k-negations/ 代码 class Solution:def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:nums.sort(keylambda x: abs(x),…

一款攻击面管理必备工具-Goby

引言 在正式介绍Goby之前,我们先简单介绍下网络功防的基本常识: 首先,对于攻击方,我们需要了解一个常见的攻击过程: 攻击者需要明确探测目标,锁定目标的地理位置、IP、域名等基本信息;对目标ip、域名进行存活性判定,对其操作系统、开放端口、服务等信息进行识别;针对…