各位同学,接下来的二天课程中,我们继续学习面向对象的相关课程。面向对象是写Java程序的核心套路,如何你不懂面向对象,那就相当于Java你白学了。所以在接下来的二天时间里,各位同学也需要克服重重困难好好学习。
前面我们说过面向对象最核心的套路是:设计对象来处理数据,解决问题。 如果你把面向对象高级这一部分课程学好,你设计出来的对象将更加好用。
在正式学习面向对象高级课程之前,我给大家提一些学习上的建议。目前我们学习的面向对象高级部分的知识点,就像一个一个的螺丝钉,在学习过程中你可能并不知道这些螺丝钉是用在哪里的,解决的什么问题。必须等这些内容都学习完之后,才能知道用这些螺丝钉可以用来搞飞机、造航母、造火箭。
所以,现阶段我们在学习过程中,主要关注下面几点就可以了。等整个基础课程学习完之后,再慢慢感在到哪里用。
一,类的私有成员和公共成员
1.1 私有成员
类的成员声明前加上私有访问控制符private,则成员只能被该类自身访问和修改,而不能被其他类(包括该类的子类)访问。达到了对数据最高级别保护的目的。
示例:
public class demo{ private int age = 100; public int getAge(){ return age; //可以在类的内部方法中使用private成员,但外部类不可以 } }
那么外部类怎么访问一个类的内部私有成员呢?比如上个示例中,可以通过公有的成中方法来访问私有的成中属性。如果一个方法被声明为私有的,则不可以被外部类访问调用。
1.2 公共成员
类的成员声明前加上公共访问控制符public,则表示该成员可以被其他类所访问。造成安全性和数据封装性的下降,所以一般减少该成员的使用。
public class Demo{ private int age = 100; public String name = "sisa"; public int getAge(){ return age; //可以在类的内部方法中使用private成员,但外部类不可以 } }
上述示例中:name属性为公有的,getAge()方法为公有的,可以被外部类来访问
public class Demo01{ public static void main(String[] args){ Demo demo = new Demo(); demo.name = "sisa2023"; int age = demo.getAge(); } }
1.3 缺省访问控制符
若在类成员的前面不加任何访问控制符,则该成员具有缺省的访问控制特性。
缺省访问控制权,表示这个成员只能被同一个包(类库)中的类所访问和调用,如果一个子类与父类位于不同的包中,子类也不能访问父类中的缺省访问控制成员,也就是说其他包中的任何类都不能访问缺省访问控制成员。
同理,对于类来说,如果一个类没有访问控制符,说明它具有缺省访问控制特性。
二、静态
接下来,我们学习一下面向对象编程中很常见的一个关键字static.
static读作静态,可以用来修饰成员变量,也能修饰成员方法。我们先来学习static修饰成员变量。
1.1 static修饰成员变量
Java中的成员变量按照有无static修饰分为两种:类变量、实例变量。它们的区别如下图所示:
由于静态变量是属于类的,只需要通过类名就可以调用:类名.静态变量
实例变量是属于对象的,需要通过对象才能调用:对象.实例变量
- 下面是代码演示(注意静态变量,和实例变量是如何调用的)
为了让大家对于这两种成员变量的执行过程理解更清楚一点,在这里给大家在啰嗦几句,我们来看一下上面代码的内存原理。
- 最后总结一下
- 1.类变量:属于类,在内存中只有一份,用类名调用 - 2.实例变量:属于对象,每一个对象都有一份,用对象调用
1.2 static修饰成员变量的应用场景
学习完static修饰成员变量的基本使用之后,接下来我们学习一下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也分为两类:类方法、实例方法
有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修饰的方法,需要创建对象后才能调用,是因为实例方法中可能会访问实 例变量,而实例变量需要创建对象后才存在。 所以实例方法,必须创建对象后才能调用。
关于static修饰成员变量、和静态修饰成员方法这两种用法,到这里就学习完了。
1.4 工具类
学习完static修饰方法之后,我们讲一个有关类方法的应用知识,叫做工具类。
如果一个类中的方法全都是静态的,那么这个类中的方法就全都可以被类名直接调用,由于调用起来非常方便,就像一个工具一下,所以把这样的类就叫做工具类。
- 我们写一个生成验证码的工具类
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; } }
- 接着可以在任何位置调用
MyUtils
的createCOde()方法
产生任意个数的验证码
//比如这是一个登录界面 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的注意事项
各位同学,到现在在我们已经学会了static修饰的变量、方法如何调用了。但是有一些注意事项还是需要给大家说明一下,目的是让大家知道,使用static写代码时,如果出错了,要知道为什么错、如何改正。
public class Student { static String schoolName; // 类变量 double score; // 实例变量 // 1、类方法中可以直接访问类的成员,不可以直接访问实例成员。 public static void printHelloWorld(){ // 注意:同一个类中,访问类成员,可以省略类名不写。 schoolName = "DTS"; 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 = "sisa2"; //对的 printHelloWorld2(); //对的 System.out.println(score); //对的 printPass2(); //对的 System.out.println(this); //对的 } }
1.6 static应用(代码块)
各位同学,接下来我们再补充讲解一个知识点,叫代码块;代码块根据有无static修饰分为两种:静态代码块、实例代码块
我们先类学习静态代码块:
public class Student { static int number = 80; static String schoolName = "sisa"; // 静态代码块 static { System.out.println("静态代码块执行了~~"); schoolName = "sisa"; } }
静态代码块不需要创建对象就能够执行
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); // sisa } }
执行上面代码时,发现没有创建对象,静态代码块就已经执行了。
关于静态代码块重点注意:静态代码块,随着类的加载而执行,而且只执行一次。
再来学习一下实例代码块
实例代码块的作用和构造器的作用是一样的,用来给对象初始化值;而且每次创建对象之前都会先执行实例代码块。
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); } }
对于实例代码块重点注意:实例代码块每次创建对象之前都会执行一次
三、构造方法和重载
3.1 构造方法
构造方法(constructor)是一种特殊的方法,它是在对象被创建时初始化对象的成员的方法,也称为构造器。它有如下特点。
1、构造方法的方法名与类名相同。
2、构造方法没有返回值,也不能有void。
3、构造方法的主要作用是对类对象的初始化工作。
4、构造方法一般不能由编程人员显式地直接调用,而是用new来调用。
5、在创建一个类的对象的同时,系统会自动调用该类的构造方法为新的对象初始化。
6、可带参数,还可以完成赋值之外的其他复杂操作
如果省略构造方法,Java编译器会自动为该类生成一个默认的构造方法,程序在创建对象时会自动调用默认的构造方法。默认的构造方法没有参数,在其方法体中也没有任何代码,即什么也不做。若class前面有public修饰符,则默认的构造方法前面也是public。一旦用户为某类定义了构造方法,系统就不再提供默认的构造方法,这是Java的覆盖所致。
关于构造器在第4章己讲述。
3.3 方法重载
面向对象的三大特性之一:多态性:一个程序中同名的多个不同方法共存的情况。常用重载和覆盖(重写)。
方法的重载是实现“多态”的方法之一。
方法重载的特征:
1、方法的重载是指方法带有不同的参数,但使用相同的名字。
2、方法的参数不同则表示实现不同的功能,但功能相似。
所谓参数不同是指:参数个数不同、参数类型不同、参数的顺序不同。参数的名字不同不能说明是方法的重载。
3、方法的重载和返回值没有关系
示例:
int add(int x, int y); int add(int x, int y, int z); float add(float f1, float f2); float add(float f1, int y); float add(int y, float f1); float add(int x, int y); int add(int u, int v);
构造方法的重载:方法名相而参数不同
public class Student{ private int age; private String name; public Student(){ } public Student(int age,String name){ this.age = age; this.name = name; } }
从某一构造方法内调用另一构造方法,必须通过关键字this来调用的,否则编译出错。
this关键字必须写在构造方法内的第一行位置。
public class Student{ private int age; private String name; public Student(){ System.out.println("空参构造方法"); } public Student(int age,String name){ this.Student(); System.out.println("非空参构造方法"); } }
注意:
构造方法一般都是public,因为它们在创建对象时,是在类的外部被系统自动调用的。 构造函数若被声明为private,则无法在构造方法所在的类以外的地方被调用,但在该类的内部还是可以被调用。
最新Java基础系列课程--Day07-面向对象的特性(二)https://developer.aliyun.com/article/1423501