java面向对象高级

一、静态

static读作静态,可以用来修饰成员变量,也能修饰成员方法。我们先来学习static修饰成员变量。

1.1 static修饰成员变量

Java中的成员变量按照有无static修饰分为两种:类变量、实例变量。它们的区别如下图所示:

由于静态变量是属于类的,只需要通过类名就可以调用:类名.静态变量

实例变量是属于对象的,需要通过对象才能调用:对象.实例变量

  • 下面是代码演示(注意静态变量,和实例变量是如何调用的)

我们来看一下上面代码的内存原理。

  • 最后总结一下

- 1.类变量:属于类,在内存中只有一份,用类名调用
- 2.实例变量:属于对象,每一个对象都有一份,用对象调用

1.2 static修饰成员变量的应用场景

在实际开发中,如果某个数据只需要一份,且希望能够被共享(访问、修改),则该数据可以定义成类变量来记住。

我们看一个案例**

需求:系统启动后,要求用于类可以记住自己创建了多少个用户对象。**

  • 第一步:先定义一个User类,在用户类中定义一个static修饰的变量,用来表示在线人数;

public class User{public static int number;//每次创建对象时,number自增一下public User(){User.number++;}
}
  • 第二步:再写一个测试类,再测试类中创建4个User对象,再打印number的值,观察number的值是否再自增。

public class Test{public static void main(String[] args){//创建4个对象new User();new User();new User();new User(); //查看系统创建了多少个User对象System.out.println("系统创建的User对象个数:"+User.number);}
}

运行上面的代码,查看执行结果是:系统创建的User对象个数:4

1.3 static修饰成员方法

成员方法根据有无static也分为两类:类方法、实例方法

有static修饰的方法,是属于类的,称为类方法;调用时直接用类名调用即可。

无static修饰的方法,是属于对象的,称为实例方法;调用时,需要使用对象调用。

我们看一个案例,演示类方法、实例方法的基本使用

  • 先定义一个Student类,在类中定义一个类方法、定义一个实例方法

public class Student{double score;//类方法:public static void printHelloWorld{System.out.println("Hello World!");System.out.println("Hello World!");}//实例方法(对象的方法)public void printPass(){//打印成绩是否合格System.out.println(score>=60?"成绩合格":"成绩不合格");}
}
  • 在定义一个测试类,注意类方法、对象方法调用的区别

public class Test2{public static void main(String[] args){//1.调用Student类中的类方法Student.printHelloWorld();//2.调用Student类中的实例方法Student s = new Student();        s.printPass();//使用对象也能调用类方法【不推荐,IDEA连提示都不给你,你就别这么用了】s.printHelloWorld();}
}

搞清楚类方法和实例方法如何调用之后,接下来再啰嗦几句,和同学们聊一聊static修饰成员方法的内存原理。

1.类方法:static修饰的方法,可以被类名调用,是因为它是随着类的加载而加载的;所以类名直接就可以找到static修饰的方法2.实例方法:非static修饰的方法,需要创建对象后才能调用,是因为实例方法中可能会访问实          例变量,而实例变量需要创建对象后才存在。所以实例方法,必须创建对象后才能调用。

1.4 工具类

如果一个类中的方法全都是静态的,那么这个类中的方法就全都可以被类名直接调用,由于调用起来非常方便,就像一个工具一下,所以把这样的类就叫做工具类。

  • 我们写一个生成验证码的工具类

public class MyUtils{public static String createCode(int n){//1.定义一个字符串,用来记录产生的验证码String code = "";//2.验证码是由所有的大写字母、小写字母或者数字字符组成//这里先把所有的字符写成一个字符串,一会从字符串中随机找字符String data = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKMNOPQRSTUVWXYZ";//3.循环n次,产生n个索引,再通过索引获取字符Random r = new Random();for(int i=0; i<n; i++){int index = r.nextInt(data.length());char ch = data.charAt(index);//4.把获取到的字符,拼接到code验证码字符串上。code+=ch;}//最后返回code,code的值就是验证码return code;}
}
  • 接着可以在任何位置调用MyUtilscreateCOde()方法产生任意个数的验证码

//比如这是一个登录界面
public class LoginDemo{public static void main(String[] args){System.out.println(MyUtils.createCode());}
}
//比如这是一个注册界面
public class registerDemo{public static void main(String[] args){System.out.println(MyUtils.createCode());}
}

工具类的使用就是这样子的,学会了吗?

在补充一点,工具类里的方法全都是静态的,推荐用类名调用为了防止使用者用对象调用。我们可以把工具类的构造方法私有化。

public class MyUtils{//私有化构造方法:这样别人就不能使用构造方法new对象了private MyUtils(){}//类方法public static String createCode(int n){...}
}

1.5 static的注意事项

public class Student {static String schoolName; // 类变量double score; // 实例变量
​// 1、类方法中可以直接访问类的成员,不可以直接访问实例成员。public static void printHelloWorld(){// 注意:同一个类中,访问类成员,可以省略类名不写。schoolName = "黑马";printHelloWorld2();
​System.out.println(score); // 报错的printPass(); // 报错的
​ystem.out.println(this); // 报错的}// 类方法public static void printHelloWorld2(){
​}// 实例方法public void printPass2(){
​}// 实例方法// 2、实例方法中既可以直接访问类成员,也可以直接访问实例成员。// 3、实例方法中可以出现this关键字,类方法中不可以出现this关键字的public void printPass(){schoolName = "黑马2"; //对的printHelloWorld2(); //对的
​System.out.println(score); //对的printPass2(); //对的
​System.out.println(this); //对的}
}

1.6 static应用(代码块)

代码块根据有无static修饰分为两种:静态代码块、实例代码块

我们先类学习静态代码块:

public class Student {static int number = 80;static String schoolName = "黑马";// 静态代码块static {System.out.println("静态代码块执行了~~");schoolName = "黑马";}
}

静态代码块不需要创建对象就能够执行

public class Test {public static void main(String[] args) {// 目标:认识两种代码块,了解他们的特点和基本作用。System.out.println(Student.number);System.out.println(Student.number);System.out.println(Student.number);
​System.out.println(Student.schoolName); // 黑马}
}

执行上面代码时,发现没有创建对象,静态代码块就已经执行了。

关于静态代码块重点注意:静态代码块,随着类的加载而执行,而且只执行一次。

再来学习一下实例代码块

实例代码块的作用和构造器的作用是一样的,用来给对象初始化值;而且每次创建对象之前都会先执行实例代码块。

public class Student{//实例变量int age;//实例代码块:实例代码块会执行在每一个构造方法之前{System.out.println("实例代码块执行了~~");age = 18;System.out.println("有人创建了对象:" + this);}
​public Student(){System.out.println("无参数构造器执行了~~");}
​public Student(String name){System.out.println("有参数构造器执行了~~");}
}

接下来在测试类中进行测试,观察创建对象时,实例代码块是否先执行了。

public class Test {public static void main(String[] args) {Student s1 = new Student();Student s2 = new Student("张三");System.out.println(s1.age);System.out.println(s2.age);}
}

注意:实例代码块每次创建对象之前都会执行一次

1.7 static应用(单例设计模式)

所谓设计模式指的是,一类问题可能会有多种解决方案,而设计模式是在编程实践中,多种方案中的一种最优方案。

二、继承

2.1 继承快速入门

面向对象编程之所以能够能够被广大开发者认可,有一个非常重要的原因,是因为它有三大特征,继承、封装和多态。

接下来,我们演示一下使用继承来编写代码,注意观察继承的特点。

public class A{//公开的成员public int i;public void print1(){System.out.println("===print1===");}//私有的成员private int j;private void print2(){System.out.println("===print2===");}
}

然后,写一个B类,让B类继承A类。在继承A类的同时,B类中新增一个方法print3

public class B extends A{public void print3(){//由于i和print1是属于父类A的公有成员,在子类中可以直接被使用System.out.println(i); //正确print1(); //正确//由于j和print2是属于父类A的私有成员,在子类中不可以被使用System.out.println(j); //错误print2();}
}

接下来,我们再演示一下,创建B类对象,能否调用父类A的成员。再写一个测试类

public class Test{public static void main(String[] args){B b = new B();//父类公有成员,子类对象是可以调用的System.out.println(i); //正确b.print1();//父类私有成员,子类对象时不可以调用的System.out.println(j); //错误b.print2(); //错误}
}

子类对象实际上是由子、父类两张设计图共同创建出来的。

所以,在子类对象的空间中,既有本类的成员,也有父类的成员。但是子类只能调用父类公有的成员。

2.2 继承的好处

我们通过一个案例来学习

观察代码发现,我们会发现Teacher类中和Consultant类中有相同的代码;其实像这种两个类中有相同代码时,没必要重复写。

我们可以把重复的代码提取出来,作为父类,然后让其他类继承父类就可以了,这样可以提高代码的复用性。改造后的代码如下:

接下来使用继承来完成上面的案例,这里只演示People类和Teacher类,然后你尝试自己完成Consultant类。

  • 先写一个父类 People,用来设计Teacher和Consultant公有的成员。

public class People{private String name;public String getName(){return name;}public void setName(String name){this.name=name;}
}
  • 再写两个子类Teacher继承People类,同时在子类中加上自己特有的成员。

public class Teacher extends People{private String skill; //技能public String getSkill(){return skill;}public void setSkill(String skill){this.skill=skill;}public void printInfo(){System.out.println(getName()+"具备的技能:"+skill);}
}
  • 最后再写一个测试类,再测试类中创建Teacher、Consultant对象,并调用方法。

public class Test {public static void main(String[] args) {// 目标:搞清楚继承的好处。Teacher t = new Teacher();t.setName("播仔");t.setSkill("Java、Spring");System.out.println(t.getName());System.out.println(t.getSkill());t.printInfo();}
}

执行代码,打印结果如下:

关于继承的好处我们只需要记住:继承可以提高代码的复用性

2.3 权限修饰符

在刚才使用继承编写的代码中我们有用到两个权限修饰符,一个是public(公有的)、一个是private(私有的),实际上还有两个权限修饰符,一个是protected(受保护的)、一个是缺省的(不写任何修饰符)。

什么是权限修饰符呢?

权限修饰符是用来限制类的成员(成员变量、成员方法、构造器...)能够被访问的范围。

每一种权限修饰符能够被访问的范围如下

下面我们用代码演示一下,在本类中可以访问到哪些权限修饰的方法。

public class Fu {// 1、私有:只能在本类中访问private void privateMethod(){System.out.println("==private==");}
​// 2、缺省:本类,同一个包下的类void method(){System.out.println("==缺省==");}
​// 3、protected: 本类,同一个包下的类,任意包下的子类protected void protectedMethod(){System.out.println("==protected==");}
​// 4、public: 本类,同一个包下的类,任意包下的子类,任意包下的任意类public void publicMethod(){System.out.println("==public==");}
​public void test(){//在本类中,所有权限都可以被访问到privateMethod(); //正确method(); //正确protectedMethod(); //正确publicMethod(); //正确}
}

接下来,在和Fu类同一个包下,创建一个测试类Demo,演示同一个包下可以访问到哪些权限修饰的方法。

public class Demo {public static void main(String[] args) {Fu f = new Fu();// f.privateMethod();   //私有方法无法使用f.method();f.protectedMethod();f.publicMethod();}
}

2.4 单继承、Object

刚才我们写的代码中,都是一个子类继承一个父类,那么有同学问到,一个子类可以继承多个父类吗?

Java语言只支持单继承,不支持多继承,但是可以多层继承。就像家族里儿子、爸爸和爷爷的关系一样:一个儿子只能有一个爸爸,不能有多个爸爸,但是爸爸也是有爸爸的。

public class Test {public static void main(String[] args) {// 目标:掌握继承的两个注意事项事项。// 1、Java是单继承的:一个类只能继承一个直接父类;// 2、Object类是Java中所有类的祖宗。A a = new A();B b = new B();
​ArrayList list = new ArrayList();list.add("java");System.out.println(list.toString());}
}
​
class A {} //extends Object{}
class B extends A{}
// class C extends B , A{} // 报错
class D extends B{}

2.5 方法重写

什么是方法重写

当子类觉得父类方法不好用,或者无法满足父类需求时,子类可以重写一个方法名称、参数列表一样的方法,去覆盖父类的这个方法,这就是方法重写。

注意:重写后,方法的访问遵循就近原则。下面我们看一个代码演示

写一个A类作为父类,定义两个方法print1和print2

public class A {public void print1(){System.out.println("111");}
​public void print2(int a, int b){System.out.println("111111");}
}

再写一个B类作为A类的子类,重写print1和print2方法。

public class B extends A{// 方法重写@Override // 安全,可读性好public void print1(){System.out.println("666");}
​
​// 方法重写@Overridepublic void print2(int a, int b){System.out.println("666666");}
}

接下来,在测试类中创建B类对象,调用方法

public class Test {public static void main(String[] args) {// 目标:认识方法重写,掌握方法重写的常见应用场景。B b =  new B();b.print1();b.print2(2, 3);}
}

执行代码,我们发现真正执行的是B类中的print1和print2方法

知道什么是方法重写之后,还有一些注意事项,需要和大家分享一下。

- 1.重写的方法上面,可以加一个注解@Override,用于标注这个方法是复写的父类方法
- 2.子类复写父类方法时,访问权限必须大于或者等于父类方法的权限public > protected > 缺省
- 3. 重写的方法返回值类型,必须与被重写的方法返回值类型一样,或者范围更小
- 4. 私有方法、静态方法不能被重写,如果重写会报错。

方法重写的应用场景

方法重写的应用场景之一就是:子类重写Object的toString()方法,以便返回对象的内容。

比如:有一个Student类,这个类会默认继承Object类。

public class Student extends Object{private String name;private int age;
​public Student() {}
​public Student(String name, int age) {this.name = name;this.age = age;}
​public String getName() {return name;}
​public void setName(String name) {this.name = name;}
​public int getAge() {return age;}
​public void setAge(int age) {this.age = age;}
}

其实Object类中有一个toString()方法,直接通过Student对象调用Object的toString()方法,会得到对象的地址值。

public class Test {public static void main(String[] args) {Student s = new Student("播妞", 19);// System.out.println(s.toString());System.out.println(s);}
}

但是,此时不想调用父类Object的toString()方法,那就可以在Student类中重新写一个toSting()方法,用于返回对象的属性值。

package com.itheima.d12_extends_override;
​
public class Student extends Object{private String name;private int age;
​public Student() {}
​public Student(String name, int age) {this.name = name;this.age = age;}
​public String getName() {return name;}
​public void setName(String name) {this.name = name;}
​public int getAge() {return age;}
​public void setAge(int age) {this.age = age;}
​@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}

重新运行测试类,结果如下

好了,到这里方法什么是方法重写,以及方法重写的应用场景我们就学习完了。

2.6 子类中访问成员的特点

  • 原则:在子类中访问其他成员(成员变量、成员方法),是依据就近原则的

定义一个父类,代码如下

public class F {String name = "父类名字";
​public void print1(){System.out.println("==父类的print1方法执行==");}
}

再定义一个子类,代码如下。有一个同名的name成员变量,有一个同名的print1成员方法;

public class Z extends F {String name = "子类名称";public void showName(){String name = "局部名称";System.out.println(name); // 局部名称}
​@Overridepublic void print1(){System.out.println("==子类的print1方法执行了=");}
​public void showMethod(){print1(); // 子类的}
}

接下来写一个测试类,观察运行结果,我们发现都是调用的子类变量、子类方法。

public class Test {public static void main(String[] args) {// 目标:掌握子类中访问其他成员的特点:就近原则。Z z = new Z();z.showName();z.showMethod();}
}
  • 如果子类和父类出现同名变量或者方法,优先使用子类的;此时如果一定要在子类中使用父类的成员,可以加this或者super进行区分。

public class Z extends F {String name = "子类名称";
​public void showName(){String name = "局部名称";System.out.println(name); // 局部名称System.out.println(this.name); // 子类成员变量System.out.println(super.name); // 父类的成员变量}
​@Overridepublic void print1(){System.out.println("==子类的print1方法执行了=");}
​public void showMethod(){print1(); // 子类的super.print1(); // 父类的}
}

2.7 子类中访问构造器的特点

子类中访问构造器的语法规则

  • 首先,子类全部构造器,都会先调用父类构造器,再执行自己。

    执行顺序,如下图按照① ② ③ 步骤执行:

子类访问构造器的应用场景

  • 如果不想使用默认的super()方式调用父类构造器,还可以手动使用super(参数)调用父类有参数构造器。

在本类中访问自己的构造方法

通过super()super(参数)可以访问父类的构造器。有时候我们也需要访问自己类的构造器。语法如下

this(): 调用本类的空参数构造器
this(参数): 调用本类有参数的构造器

最后我们被this和super的用法在总结一下

访问本类成员:this.成员变量   //访问本类成员变量this.成员方法   //调用本类成员方法this()         //调用本类空参数构造器this(参数)      //调用本类有参数构造器访问父类成员:super.成员变量  //访问父类成员变量super.成员方法  //调用父类成员方法super()        //调用父类空参数构造器super(参数)     //调用父类有参数构造器注意:this和super访问构造方法,只能用到构造方法的第一句,否则会报错。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQL注入漏洞解析--less-46

我们先看一下46关 他说让我们先输入一个数字作为sort,那我们就先输入数字看一下 当我们分别输入1&#xff0c;2&#xff0c;3可以看到按照字母顺序进行了排序&#xff0c;所以它便是一个使用了order by语句进行排序的查询的一种查询输出方式 当输入时出现报错提示&#xff0c;说…

【软件测试】--功能测试1

一、测试介绍 什么是软件&#xff1f; 控制计算机硬件工作的工具。 什么是软件测试&#xff1f; 使用技术手段验证软件是否满足需求 软件测试的目的&#xff1f; 减少软件缺陷&#xff0c;保证软件质量。 测试主流技能 1、功能测试 2、自动化测试 3、接口测试 4、性能测试 ​…

图解 Electron 进程模型

此前&#xff0c;已经介绍了《如何从 0 开始&#xff0c;创建一个 Electron 的 App》&#xff0c;每个人就有了一个梦开始的地方。如果想实现一个功能丰富的 App&#xff0c;了解一点基础知识&#xff0c;是非常必要的。比如&#xff0c;Electron 的进程模型。 一、简介 Chrome…

数据湖delta lake

Table of Content1. 课程2. 前置技能3. 一、数据湖概念[了解] 3.1. 1.1 企业的数据困扰 3.1.1. 困扰一&#xff1a;互联网的兴起和数据孤岛3.1.2. 困扰二&#xff1a;非结构化数据3.1.3. 困扰三&#xff1a;保留原始数据3.1.4. 补充&#xff1a;什么是结构化&#xff1f; 3.1.4…

【Simulink系列】——动态系统仿真 之 混合系统

声明&#xff1a;本系列博客参考有关专业书籍&#xff0c;截图均为自己实操&#xff0c;仅供交流学习&#xff01; 一、混合系统概述 由不同类型系统共同构成的系统称为混合系统&#xff01;仿真时必须考虑连续信号和离散信号的采样匹配问题&#xff0c;一般使用变步长连续求…

AI智能分析网关V4智慧工厂视频智能监管与风险预警平台建设方案

一、背景需求分析 1&#xff09;随着信息技术的迅猛发展和制造业竞争的加剧&#xff0c;智慧工厂成为了推动制造业转型升级的重要引擎。智慧工厂解决方案通过整合物联网、人工智能、大数据分析等先进技术&#xff0c;实现生产过程的智能化、自动化和高效化&#xff0c;为企业提…

初识Lombok

前言 最近读一些公司的业务代码&#xff0c;发现近几年的java项目工程中都使用了lombok&#xff0c;lombok是一个可以自动生成get,set、toString等模板类方法的工具框架&#xff0c;程序再引入lombok后&#xff0c;添加一个注解便可以不写get\set\toString等方法。 Lombok示例…

【Java程序设计】【C00286】基于Springboot的生鲜交易系统(有论文)

基于Springboot的生鲜交易系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的生鲜交易系统 本系统分为系统功能模块、管理员功能模块、用户功能模块以及商家功能模块。 系统功能模块&#xff1a;在系统首页可以…

定制红酒:设计专属标签与包装,打造与众不同个性

在云仓酒庄洒派的定制红酒服务中&#xff0c;为消费者提供个性化、专属的标签与包装设计是提升红酒与众不同性和纪念价值的关键环节。通过巧妙的设计&#xff0c;消费者可以打造出与众不同的红酒&#xff0c;展现自己的个性与品味。 首先&#xff0c;标签设计是展现红酒个性的重…

经典文献阅读之--InsightMapper(深入研究矢量化高精地图的内部实例信息)

0. 简介 高精地图作为自动驾驶中最关键的组成部分&#xff0c;矢量化高精&#xff08;HD&#xff09;地图包含有关周围道路元素的详细信息&#xff0c;这对于现代自动驾驶汽车的各项下游任务是至关重要的&#xff0c;例如车辆规划和控制。最近的工作试图直接检测矢量化高精地图…

微服务篇之任务调度

一、xxl-job的作用 1. 解决集群任务的重复执行问题。 2. cron表达式定义灵活。 3. 定时任务失败了&#xff0c;重试和统计。 4. 任务量大&#xff0c;分片执行。 二、xxl-job路由策略 1. FIRST&#xff08;第一个&#xff09;&#xff1a;固定选择第一个机器。 2. LAST&#x…

提供英语自我介绍(带翻译)的软件有哪些?分享五款实用软件

提供英语自我介绍(带翻译)的软件有哪些&#xff1f;在全球化日益加速的今天&#xff0c;英语自我介绍已成为我们展示个人风采、赢得机会的重要一环。本文将为您介绍五款提供英语自我介绍及翻译功能的软件&#xff0c;帮助您轻松撰写并呈现一个吸引人的英文自我介绍。 1. 语音翻…