JAVA学习资料(5)————修饰符public、private、protected等
前言
1、包
在之前创建JAVA的第一个实例程序时(JAVA学习资料(2)————JAVA开发环境的配置),其中有一步创建包的操作,后面也会详细讲解包的用法,这里先了解一下什么是包:
- 把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。
- 如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。
- 包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。
这就相当于一个真正的包了,把你认为相似的类都存放在一个包包里,方便调用和查找修改。
2、类的继承
类的继承是一个很复杂的知识,后面的课程会详细解释,这里先认识一下什么是继承。一个程序中不止有一个类,各个类之间都是存在关系的,那么都有什么关系呢?在JAVA类的继承中,类与类是有所谓的“父子关系”的,也就是说,一个类可以是另一个类的父亲,而另一个类可以是这个类的孩子。我们管这个“父亲”叫“父类”或者“基类”,管这个孩子叫“子类”。同理,孩子也可以有孩子,这个就是“孙类”,一个类可以有很多子孙。
一、访问控制修饰符
接下来开始正式学习修饰符了,修饰符分为访问控制修饰符和非访问修饰符,访问控制修饰符的主要功能是控制这个函数/变量的访问权限,在JAVA中,访问控制修饰符共有以下四种:
- default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
- private(隐私的) : 私有成员,在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
- public(公开的) : 公有成员,对所有类可见。使用对象:类、接口、变量、方法
- protected(保护的) : 保护成员,对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
这里有几点需要注意:
- 父类中声明为 public 的方法在子类中也必须为 public。
- 父类中声明为 protected 的方法在子类中要么声明为 protected,要么声明为 public,不能声明为 private。
- -父类中声明为 private 的方法,不能够被继承。
下表概括一下在不同位置,用不同修饰符定义的变量或函数是否能被访问:
修饰符 | 当前类 | 同一包内 | 子孙类(同一包) | 子孙类(不同包) | 其他包 |
---|---|---|---|---|---|
default | √ | √ | √ | X | X |
public | √ | √ | √ | √ | √ |
protected | √ | √ | √ | √ / X | X |
private | X | X | X | X | X |
接下来详细说明一下四个修饰符:
1.default
使用默认访问修饰符声明的变量和方法,对同一个包内的类是可见的,但是别的包的类就看不到他了,就没办法访问他了。
2.public
被声明为 public 的类、函数、构造函数和接口能够被任何其他类访问。如果几个相互访问的 public 类分布在不同的包中,则需要导入相应 public 类所在的包(这个导入方法后面会讲)。由于类的继承性,类所有的公有函数和变量都能被其子类继承,都能被其子类随意访问。
3.protected
protected 需要从以下两个点来分析说明:
- 子类与基类在同一包中:就可以随便访问。被声明为 protected 的变量、函数能被同一个包中的任何其他类访问;
- 子类与基类不在同一包中:就不能访问咯,只能访问继承的东西。在子类中,子类实例可以访问其从基类继承而来的 protected 函数,而不能访问基类实例的protected方法。
4.private
Private 访问修饰符的使用主要用来隐藏类的实现细节和保护类的数据,有很强的安全性。
私有访问修饰符是最严格的访问级别,所以被声明为 private 的函数、变量和构造函数只能被所属类访问,并且类不能声明为 private。声明为私有访问类型的变量只能通过类中的函数被外部类访问。
下面是一个实例:
public class Maomao {
private int age;
public int getage() {
return age;
}
public int setage(int newage) {
age = newage;
}
}
在这段代码中,age作为Maomao类的私有成员,类中有俩个共有成员函数,为getage和setage,该age成员在类外部是不可使用maomao.age调用的,但是也可以修改age的值,你看,在Maomao类中这两个函数是public的,所以在类外可以调用,在类外通过调用getage函数,可以读取(返回)age的值。在类外通过调用setage函数,就可以修改age的值了,因为这里修改age值的函数setage是Maomao类内的函数,可以访问私有成员。
二、非访问修饰符
1.static
在Java中并不存在全局变量的概念,但是我们可以通过static来实现一个“伪全局”的概念,在Java中static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,当然也可以修饰代码块。
(1)static变量
在类中一个成员变量可用 static 关键字来修饰,这样的成员变量称为 static 成员变量,或静态成员变量。而没有用 static 关键字修饰的成员变量称为非静态成员变量。
静态成员变量是属于类的,也就是说,该成员变量并不属于某个对象,即使有多个该类的对象实例,静态成员变量也只有一个。只要静态成员变量所在的类被加载,这个静态成员变量就会被分配内存空间。因此在引用该静态成员变量时,通常不需要生成该类的对象,而是通过类名直接引用。引用的方法是“类名 . 静态变量名”。当然仍然可以通过“对象名 . 静态变量名”的方式引用该静态成员变量。相对应的非静态成员变量则属于对象而非类,只有在内存中构建该类对象时,非静态成员变量才被分配内存空间。
public class Maomao {
public static int age;
}
(2)static函数
Java 中也支持用 static 关键字修饰的成员函数,即静态成员函数。与此相对应的没有用 static 修饰的成员方法称为非静态成员函数。
与静态成员变量类似,静态成员方法是类函数,它属于类本身而不属于某个对象。因此静态成员函数不需要创建对象就可以被调用,而非静态成员函数则需要通过对象来调用。
特别需要注意的是,在静态成员函数中不能使用 this、super 关键字,也不能调用非静态成员函数,同时不能引用非静态成员变量。这个道理是显而易见的,因为静态成员函数属于类而不属于某个对象,而 this、super 都是对象的引用,非静态成员函数和成员变量也都属于对象。所以当某个静态成员函数被调用时,该类的对象可能还没有被创建,那么在静态成员函数中调用对象属性的函数或成员变量显然是不合适的。即使该类的对象已经被创建,也是无法确定它究意是调用哪个对象的函数,或是哪个对象中的成员变量的。所以在这里特别强调这一点。
public class Maomao {
public static int age;
public static int getage() {
return Maomao.age;//注意这里不能写成return age!
}
}
(3)static代码块
static 代码块又称为静态代码块,或静态初始化器。它是在类中独立于成员函数的代码块。static 代码块不需要程序主动调用,在编译器加载类时系统会执行 static 代码块,因此在static 代码块中可以做一些类成员变量的初始化工作。如果一个类中有多个 static 代码块,编译器将会按顺序依次执行。需要注意的是,所有的static 代码块只能在编译器加载类时被执行一次。
public class Maomao {
public static int age;
public static int getage() {
return Maomao.age;//注意这里不能写成return age!
}
static {
Maomao.age = 2;
}
}
2.final
(1)final变量
final 表示"最后的、最终的"含义,变量一旦赋值后,不能被重新赋值。被 final 修饰的实例变量必须赋一个初始值。
final 修饰符通常和 static 修饰符一起使用来创建类常量。
public class Maomao {
public final int age=1;
public static final int newage=3; //之后age和newage的值都不能被修改
}
(2)final函数
父类中的 final 函数可以被子类继承,但是不能被子类重写。声明 final 函数的主要目的是防止该函数的内容被修改。
public class Maomao {
public final void setage(){
}
}
(3)final类
final 类不能被继承,没有类能够继承 final 类的任何特性。
public final class Maomao {
}
3.abstract
abstract不能和final,private,static连用
(1)abstract(抽象)类
抽象类不能用来初始化一个新的对象。声明抽象类的唯一目的是为了将来对该类进行扩充。
一个类不能同时被 abstract 和 final 修饰。如果一个类包含抽象函数,那么该类一定要声明为抽象类,否则将出现编译错误。
抽象类可以包含抽象函数和非抽象函数。
public abstract class Maomao {
public int age;
public abstract void getage(); //抽象函数
}
(2)abstract(抽象)函数
抽象函数是一种没有任何内容的函数,该函数的的具体实现由子类提供。
抽象函数不能被声明成 final 和 static。
任何继承抽象类的子类必须实现(定义)父类的所有抽象函数,除非该子类也是抽象类。
如果一个类包含若干个抽象函数,那么该类必须声明为抽象类。抽象类可以不包含抽象函数。
public abstract class Maomao {
public abstract void getage(); //抽象函数
}
class Maomao_children extends Maomao { //这是Maomao的一个子类Maomao_children
void getage(){//在子类中必须实现抽象函数
System.out.println("age");
}
}
4.synchronized
此处了解即可。在Java中,synchronized关键字是用来控制线程同步的,就是在多线程的环境下,控制synchronized修饰的变量、函数或者代码段不被多个线程同时执行(不知道什么是线程的话去看第一课)
5.transient
此处了解即可。序列化的对象包含被 transient 修饰的实例变量时,java 虚拟机(JVM)跳过该特定的变量。该修饰符包含在定义变量的语句中,用来预处理类和变量的数据类型。具体参照下面这篇文章:https://www.nopassby.com/blog?blogId=1gfq.(点此链接进入)
6.volatile
此处了解即可。volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。
最后说两句吧,开学了,开学快一周了,这周很疯狂,让人疯狂、崩溃,也一直没有精力来写博客,我看连关注都不关注我了,我也不知道现在为什么还要继续写下去,也算是安慰自己吧,总有一天会看到的,每天生活在幻想里面,只有幻想才能让自己心存希望,不然,就跌到深渊里面了,闭眼的时候做恶梦,胡思乱想,总不能睁着眼睛的时候还像做恶梦一样胡思乱想吧,总是要给自己一点鼓励和希望的,哪怕一点点小小的火花,也能照亮漆黑的世界,还会经常更新的,你要好好的。