一、知识点
重载、this关键字、构造器、static、final、封装、单例模式。
二、目标
-
认识重载及使用重载的优点。
-
深刻理解this关键字的作用。
-
掌握无参构造器、有参构造器的作用。
-
掌握成员变量、成员方法有static与没有static修饰的区别。
-
掌握final关键字的使用。
-
掌握成员变量分别被public、private、protected修饰和无修饰符修饰的区别。
三、内容分析
-
重点
-
this关键字、构造器、static、封装、单例模式。
-
-
难点
-
static的理解。
-
单例模式的封装过程。
-
四、内容
1、重载
定义:在同一个类中,方法的名字一样,参数列表不一样(包括参数类型)的两个方法是重载关系,跟返回值没有关系。
目的:为了节约方法的功能命名和提高代码的可读性
通过以下三种方式实现重载:
-
参数数量
add(int, int) add(int, int, int)
-
参数的数据类型
add(int, int) add(int, float)
-
参数的数据类型顺序
add(int, float)
add(float, int)
示例:
public static void main(String[] args) {
// 都是调用test方法,根据传参匹配对应的方法
test(); // 1
test(10); // 2
test(10, 20); // 3
test(10, "20"); // 4
test("10", 20); // 5
}
public static void test() {
System.out.println("1");
}
public static void test(int n) {
System.out.println("2");
}
public static void test(int n, int m) {
System.out.println("3");
}
public static void test(int n, String s) {
System.out.println("4");
}
public static void test(String s, int n) {
System.out.println("5");
}
2、this关键字
this只能在成员方法内使用。
对于类的对象来说,属性是每一个对象都有一份的,是数据隔离的,但是方法是多个数据共享的。不同对象调用这个方法的时候,是用this来区分不同对象的数据,this是可以隐藏的。
示例:假设有类Student(name属性,study方法),创建两个Student对象,分别调用study方法,最后打印的名字是不一样的。
public class Student {
public String name;
public void study() {
System.out.println(this.name + "好好学习!!");
}
public static void main(String[] args) {
Student student1 = new Student();
student1.name = "张三";
Student student2 = new Student();
student2.name = "李四";
// 执行的都是打印【this.name + "好好学习!!"】,但是获取的name值不一样
student1.study(); // 张三好好学习!!
student2.study(); // 李四好好学习!!
}
}
3、构造器
用于创建对象的方法,固定格式,给对象赋初始值。
我们使用new的时候相当于调用了类里面的构造器方法。
构造器本身是一个方法。
语法:
-
没有返回值,没有void
-
构造器的方法名必须和类型一致
-
在方法中要定义要初始的参数列表(非必须)
// 默认构造器
权限修饰符 类名() {
}
// 有参构造器
权限修饰符 类名(数据类型 参数) {
}
注意点:
-
如果一个类存在有参构造器,那么默认的构造器就会被覆盖,如果需要默认的构造器,就要显示的定义。
-
同一个类中的构造器可以互相调用,需用通过this()来调用,this()必须在第一行。
使用场景:需要在执行构造器功能之前,先前置初始化数据。
-
在构造器中调用其他构造器,不会创建对象,只初始化。
4、static关键字
可以一句话来概括:方便在没有创建对象的情况下来进行调用。
被static关键字修饰的不需要创建对象去调用,直接根据类名就可以去访问。
static一般用来修饰成员变量或函数。
4.1 修饰成员变量
被static修饰的成员变量叫做静态变量,也叫做类变量,说明这个变量是属于这个类的,而不是属于对象,没有被static修饰的成员变量叫做实例变量,说明这个变量是属于某个具体的对象的。
public class Student {
public String name;
public static String sex;
public static void main(String[] args) {
Student student1 = new Student();
student1.name = "张三";
student1.sex = "男";
Student student2 = new Student();
student2.name = "李四";
student2.sex = "女";
// 获取的name不一样,因为name属性是普通的成员变量,属于对象,每个对象都有自己的name数据
System.out.println(student1.name); // 张三
System.out.println(student2.name); // 李四
// 获取的sex不一样,因为sex属性是static修饰的成员变量,属于类,所有的对象共用
System.out.println(student1.sex); // 女
System.out.println(student2.sex); // 女
// staitc修饰的成员变量可以直接通过【类名.属性名】获取
System.out.println(Student.sex); // 女
// 编译报错
System.out.println(Student.name);
}
}
解析:
Student.class加载到方法区的时候,系统会自动把Student所有的静态属性和方法分配到静态区,所以我们不需要new对象就可以直接使用Student.sex访问到sex属性。
而我们访问Student.name的时候会编译报错,因为name属性是在new对象的时候,在堆内存里面开辟一块新空间才生成的,所以我们需要先new一个对象,然后通过这个对象访问到自己的name属性。
4.2 修饰方法
static修饰方法的时候,可以直接通过类名来进行调用。
public class Student {
public void study() {
System.out.println("好好学习!!");
}
public static void coding() {
System.out.println("摩擦键盘!!");
}
public static void main(String[] args) {
Student student = new Student();
// 对象可以正常调用static修饰的方法和非static修饰的方法
student.coding(); // 可以运行
student.study(); // 可以运行
// static修饰的方法还可以直接通过【类名.方法名】调用
Student.coding(); // 可以运行
Student.study(); // 编译报错
}
}
4.3 注意事项
-
静态方法只能访问静态成员(静态成员即静态成员变量和静态方法)。
-
静态方法中不可以使用this或者super关键字。
public class Student {
public String name;
public static String sex;
public void study() {
System.out.println(name + "好好学习!!");
System.out.println(sex);
}
public static void coding() {
System.out.println(sex); // 可以访问
System.out.println(name + "摩擦键盘!!"); // 编译报错
study(); // 编译报错(如果study方法改成static修饰,那就可以访问)
System.out.println(this); // 编译报错
}
}
4.4 静态代码块
语法:
class A {
// 静态代码块
static {
}
}
-
static静态代码块只在类加载时执行一次,经常用于初始化资源。优先于构造器
-
静态代码块在main之前执行。
5、final关键字
final是【最终】的意思。final是一个关键字,它可以被用来修饰类,变量以及成员方法。
修饰的成员变量会进入方法区的常量池。
5.1 修饰变量
变量分为成员变量和局部变量,他们被final修饰时有不同的注意事项。
-
修饰成员变量
被final修饰的成员变量,一定要被赋值且只能被赋值一次,且必须是在这个成员变量所在的类对象创建之前被赋值。
public class Student {
public String name;
public final int a = 10; // 必须赋初始值或者可以在构造函数赋初始值,否则会编译错误
}
public class Student {
public String name;
public final int a; // 必须赋初始值或者可以在构造函数赋初始值,否则会编译错误
public Student() {
this.a = 10;
}
}
2.修饰局部变量
被final修饰的变量,又被称为自定义常量。常量的意思是不会被改变的量。所以,被final修饰的变量即自定义常量是不能被改变的(只能被赋值一次,后续不能更改)。
final int a =s
5.2 修饰成员方法
当final关键字修饰了成员方法,则意味着这个方法不能被重写,但是可以被继承。
// 学生类
public class Student {
public String name;
public final void study() {
System.out.println("好好学习!!");
}
}
// 小学生类
public class Pupil extends Student{
// 编译报错,study是final修饰的,不能被重写
public void study() {
}
}
5.3 修饰类
当final关键字修饰一个类,则该类会成为最终类,即该类不能被继承。
// final修饰学生类
public final class Student {
}
// 不能继承final类,编译报错
public class Pupil extends Student{
}
特殊情况:享元模式
包装类中,Byte,Short,Integer,Long,Character,Boolean,在值区间为[-128,127],也会使用常量池技术
6、封装-权限修饰符
private:日常开发里面用的最多的属性,因为他足够安全(只有本类可以使用)
修饰符 | 同一个类 | 同一个包 | 不同包非子类 | 不同包子类 |
---|---|---|---|---|
private | 可以访问 | 不可以访问 | 不可以访问 | 不可以访问 |
public | 可以访问 | 可以访问 | 可以访问 | 可以访问 |
protected | 可以访问 | 可以访问 | 不可以访问 | 可以访问 |
default | 可以访问 | 可以访问 | 不可以访问 | 不可以访问 |
-
public:共有访问。对所有的类都可见。
-
protected:保护型访问。对同一个包可见,对不同的包的子类可见。
-
default:默认访问权限。只对同一个包可见,注意对不同的包的子类不可见。
-
private:私有访问。只对同一个类可见,其余都不见。【极大提高程序的安全性】
7、单例模式
单例模式是一种常用的软件设计模式。通过单例模式可以保证系统中一个类只有一个对象。
应用场景:windows资源管理器,java数据库中的连接池,网站的计数器。一般使用单例模式实现,否则难以同步。
步骤:
-
私有化构造器(防止别人也可以创建)、定义一个私有的成员变量(用于保存当前类对象)
-
定义一个类方法用于获取单例的对象
-
在类中提供一个这个类类型的类属性(要用static修饰)
-
在类方法中返回实例化对象
/**
* 懒汉式单例
*/
public class Singleton {
private static Singleton singleton;
private Singleton() {
}
public static Singleton getSingleton() {
if(singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
/**
* 饿汉式单例
*/
public class Singleton2 {
private static Singleton2 singleton = new Singleton2();
private Singleton2() {
}
public static Singleton2 getSingleton() {
return singleton;
}
}
五、小结
重点理解this关键字、构造器、static的作用,能够默写单例模式。
六、练习
-
封装狗类Dog,实现yao咬的功能。
要求:创建Dog对象。
-
调用yao()方法,打印【汪汪汪】。
-
调用yao(String str), 打印【咬xxx】,比如调用yao("骨头"), 打印【咬骨头】。
-
调用yao(Person p), 如果人的性别为男,则打印【扑上去撕咬】,如果人的性别是女,则打印【跑过去舔两口】。
2.封装矩形类Rectangle,属性(length长、width宽、area面积)。
要求:创建一个Rectangle对象的时候利用构造器传入矩形的长和宽,然后打印Rectangle对象的面积。
Rectangle rectangle = new Rectangle(10, 20);
System.out.println(rectangle.area); // 200,这里要能直接打印矩形的面积出来
3.使用idea默写两种单例模式。
以上就是本文内容,相信你学完写完一定已经理解透彻!