Java权限修饰符-public,private,protected

  最近在温习java基础,看到了修饰符,感觉这个虽然很基础,但是也有很多衍生的知识点,比如单例或者内部类这样的,所以写一遍关于权限修饰符的文章,让自己巩固一下,基础还是特别重要的 !

 

  在java中有四种权限修饰符,这四种分别是public,private,protected和默认修饰符,其中,默认修饰符又称为friendly,是指在定义类或变量的时候不加任何修饰符。接下来,由我来为大家一一介绍一下这几种修饰符,首先为public:

  

1.public

  在java中,public是指“公共的“,所以从字面意思上我们就可以大致推算出这个关键字的含义与用法了,那就是公共的,所有人都可以有权限使用的,就像公园,公共厕所,我们所有人都可以使用,这就是public。

 

  下面我们来说一下public在具体应用的范围和例子。

1.1 修饰类

  对于public,我们第一次见到的时候肯定是在创建我们的第一个java工程“Hello World”的时候见到的

public class Hello{

    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}

  在上面这个新建的Hello类中我们可以看到public同时修饰了类“public class Hello”,和方法“public static void main”,方法我们先不说,我们先来讲讲类。

  我们都知道,当我们用工具(IDEA,eclipse,MyEclipse等)创建一个类的时候,都是点击new一个java class,之后输入类名,假如我输入的是Hello,所属包是com.lxw.first,那么就会为我生成一个Hello.java文件,打开之后是如下所示代码。

package com.lxw.first;

public class Hello {
}

Java权限修饰符-public,private,protected_第1张图片Java权限修饰符-public,private,protected_第2张图片

 

  在这里,java会自动为我们创建一个public修饰的类,类名和java文件名一毛一样,说到这里,那就不得不提一下java对于类的约束了,java对于一个.java文件与类有如下几点要求:

  1.一个java文件中可以含有多个类,这些类只能用public或默认修饰符(就是不加修饰符)来修饰

  2.一个java文件只能包含一个public修饰的类,而且类名必须与文件名一致(这里的一致是区分大小写下划线等一切字符)

  3.一个java文件中可以没有public修饰的类

  ps:不加修饰符的类,在实际应用中和普通类的差别只在于作用域

  知道了这些之后,我们来写几个例子验证一下,看看我们不符合要求的话编译器是不是会报错,在开始之前,还有一点需要提前说一下,那就是默认修饰符。默认修饰符是指在类、方法、变量前不加任何的权限修饰符,而当java在编译时检测到你没有任何修饰符,这时java就会为你添加一个默认修饰符,也称friendly。默认修饰符的作用范围就是在同一个包下的其他类

  知道了默认修饰符,我们就可以开始测试了!

 

1.首先我使用工具新建了一个Yinyinyin类,之后我删除掉里面自动生成的类之后,新建如下所示三个类

Java权限修饰符-public,private,protected_第3张图片

  编译器是没有报错的,那么这个时候就说明一个java文件中可以有多个默认修饰符修饰的类,验证了我们的第一点和第三点,接下来,我们将其中的Teacher类的修饰符改为public,编译器就报了如下错误:

Java权限修饰符-public,private,protected_第4张图片

  “Class 'Teacher' is public, should be declared in a file named 'Teacher.java'“,翻译一下,就是类'Teacher'是public(公共的),应该被declared(声明)在一个名字为'Teacher.java'的文件中,这就对应了上面的第二点,此时我觉得我们还能挣扎一下,于是声明如下一个类:

Java权限修饰符-public,private,protected_第5张图片

  Look!文件名是'Yinyinyin',类名是'YInyinyin',只是变更了一个字母的大小写,java居然也不让,那就实锤了我们的第二点:一个java文件只能包含一个public修饰的类,而且类名必须与文件名一致(这里的一致是区分大小写下划线等一切字符)

  

  然后,我们来看public修饰类的使用范围,顺便和默认修饰符一起说了,接着上面的例子,看下图:

Java权限修饰符-public,private,protected_第6张图片

  我们Yinyinyin这个.java文件中写了一个名为Yinyinyin的类,之后,到一个main方法中去new一下这个类:

Java权限修饰符-public,private,protected_第7张图片

  看,是完全没有问题的。这就和我们平时新建一个类,然后去new它一样,public是公共的,无论谁都可以访问,new它。但是,但我们删除掉这个Yinyinyin的类之后,会出现什么情况呢?

Java权限修饰符-public,private,protected_第8张图片

  我们在Yinyinyin这个文件中删除掉了Yinyinyin这个类,剩下四个修饰符为默认修饰符的类,之后,我们接着去一个main中去new一个Yinyinyin,如下图:

Java权限修饰符-public,private,protected_第9张图片

  编译器会给我们报一个Cannot resolve symbol 'Yinyinyin'的错误,意为:无法识别的标识,这是因为我们虽然建立了一个Yinyinyin文件,但是却没有与之对应的YInyinyin类,有的只是四个默认修饰符修饰的类;接下来我们顺便了解一下默认修饰符,尝试在main方法中去new一下这几个类:

Java权限修饰符-public,private,protected_第10张图片

  默认修饰符的作用是在包内可用,所以我在Yinyinyin文件同一个包first下创建了Hello.java,其中new了Yinyinyin中的几个内部类,编译器没有报错,成功new了出来。

  然后我们在名为second的包下将上面的操作重新做一遍:

Java权限修饰符-public,private,protected_第11张图片

  此时编译器会报错,并且提示我们进行导包,这个时候当然要听编译器的,进行导包~~~~

  导包ing..............................................1%

  导包ing..............................................46%

  导包ing..............................................79%

  导包ing..............................................100%

  导包成功!!!!

  写累了,歇会儿..........ε=(´ο`*)))

  看结果:

  Java权限修饰符-public,private,protected_第12张图片

  依旧报错,编译器很温馨的给出了我们错误原因:'com.lxw.first.YInyinyin' is not public in 'com.lxw.first'. Cannot be accessed from outside package。翻译小能手上线:意思就是这个包不是public(公共的),不能从外部包访问,实锤+1。

 

1.2 修饰方法

  说完了类,我们来说说方法,遵循着public本来的含义,公共的,那他修饰的方法也是这样,接着上面的Yinyinyin这个文件,我们里面还有三个类,每个类中都有一个methods方法,输出一句话:

Java权限修饰符-public,private,protected_第13张图片

  在main中将这几个类new出来,直接调用对应的methods方法:

Java权限修饰符-public,private,protected_第14张图片

  莫得毛病,可以输出,别的包下也来一发~~~

Java权限修饰符-public,private,protected_第15张图片

  莫得问题,接着来试试将方法改为默认修饰符修饰:

Java权限修饰符-public,private,protected_第16张图片

  同包下先来一发,不会出意外,完全没有问题!

Java权限修饰符-public,private,protected_第17张图片

  接着,到不同的包下来一下,不出意外应该是有问题的,因为默认修饰符的作用域只在于包内:

Java权限修饰符-public,private,protected_第18张图片

  和我们创建类的时候报的错误是一样一样一样的,真是没有新意,还是方法不是public(公共的),无法从外部包内访问,相信聪明的小伙伴们已经知道了如何默认修饰符来提高代码质量了吧!

  但是这里要注意一点,那就是在接口(interface)。在接口中,所有的方法有一个默认的修饰符,那就是public abstract(公共抽象),所有的变量都有一个默认修饰符:public static final,也就是说当你在接口中不写修饰符的时候,方法的修饰符就不是默认修饰符(friendly)了,而是public abstract。而且,当在接口中新建方法的时候,一般也是不写修饰符的,写了的话,编译器也一般会给标灰,意思是无效的。

Java权限修饰符-public,private,protected_第19张图片

 

1.3 修饰变量

  写了这么多,好累啊~~~~~~~~~~~~

  public用来修饰变量,只要牢记他的特性,公共的,就ok!来人,上代码!!!!

  同样在Yinyinyin中的每个类中新建变量text.............main方法中直接输出~~~~~~~~

Java权限修饰符-public,private,protected_第20张图片

Java权限修饰符-public,private,protected_第21张图片

  可以看到,直接输出,完全莫有毛病,换个包,输出,同样莫得问题~~~~

Java权限修饰符-public,private,protected_第22张图片

 

BUT!!!!当去掉public之后,就会成为包内访问了!

Java权限修饰符-public,private,protected_第23张图片

Java权限修饰符-public,private,protected_第24张图片

Java权限修饰符-public,private,protected_第25张图片

  同样的悲剧再次发生~~~~原汁原味的错误,可以看到,变量也是遵循这个原则,不会变更滴!

 

2.private

  private(私有的),意为私有的,这个的权限的范围可要比默认修饰符(friendly)要小的多了,被private修饰之后,就只能在该类中进行访问,其他类没有其访问权限。

 

2.1 修饰类

  private用来修饰类的话只有一种情况,那就是内部类,如果直接用来修饰类的话是会报错滴(如下图)!

  Modifier 'private' not allowed here,修饰符private在这嘎达不允许你使用。

Java权限修饰符-public,private,protected_第26张图片

  所以这里需要简单说一下内部类,至于为什么是简单说,是因为内部类这块儿知识点比较多,大概认识一下就好,以后有空我会专门写一下内部类,这里先简单说一下内部类的创建的简单的使用。内部类就是类中类,是指在类中写类的写法,具体入下图所示:

Java权限修饰符-public,private,protected_第27张图片

  在Yinyinyin这个类中写了一个名为Student的类,这种写法就是内部类,内部类(Student)在其外部类(Yinyinyin)中可以通过普通方式(直接new Student)来直接新建,但是在其他类中,就需要通过特别方法来new:

Java权限修饰符-public,private,protected_第28张图片

  即为:先new出外部类,之后通过外部类来new内部类的方式。

  不过一般情况下是不会再其他类中new一个类的内部类的,因为内部类的主要作用还是解决一些外部类中的问题,减少代码的冗余度。如果一个内部类有多个类需要使用的话,那么还不如直接新建一个类。

  如下图所示,我们将内部类改为priavte之后,在其他类中就不可以new出来了:

Java权限修饰符-public,private,protected_第29张图片

Java权限修饰符-public,private,protected_第30张图片

 

2.2 修饰方法

  private用来修饰方法的话,就是只可以在本类中使用,即使是在同一个文件下,也是不可以使用的,示例如下图所示:

Java权限修饰符-public,private,protected_第31张图片

  我在Student这个类中新建一个getStudent的方法,用private修饰,之后我分别在Yinyinyin中的方法和Student的构造方法中对这个方法进行调用,可以看到,在Student中是可以调用的,但是在Yinyinyin中是无法调用的。

  这是修饰普通方法,private也可以用来修饰类的构造方法,这里划重点,这个用法可以引用出java的设计模式----单例设计模式。所以在这里详细说一下:

  构造方法:是指在类中,与类名相同,无返回值的方法,它会在类加载时调用,也就是new的时候调用。在一个类中,是支持多个构造方法的,参数类型不同即可,这就是重载(一个类中可以含有多个相同方法名,但是参数类型不同的方法)

  构造方法在类加载时会被调用,根据参数不同,会调用不同的构造方法,具体事例如下图所示:

Java权限修饰符-public,private,protected_第32张图片

Java权限修饰符-public,private,protected_第33张图片

  从上图可以看到,我们自定义了三个构造方法,当我们在new Yinyinyin这个类的时候,传入参数不同,那么就会调用不同的构造方法。如果我们在类中没有自己定义的话,那么java还会有一个默认的构造方法被调用:

Java权限修饰符-public,private,protected_第34张图片

Java权限修饰符-public,private,protected_第35张图片

  上图我们在Yinyinyin类中删除了所有的构造方法,然后重新打开编译后的字节码文件(.class文件),可以看到会有一个默认的无参构造方法。

  讲完了构造方法,那我们进入正题,构造方法既然是类加载时会被调用,那么将它修饰为private会有什么问题呢?

  如下图,我们将构造方法修饰符改为了private,代码并没有用报错:

Java权限修饰符-public,private,protected_第36张图片

  但是当我们试图new这个类的时候,报错了:

Java权限修饰符-public,private,protected_第37张图片

  'Yinyinyin()' has private access in 'com.lxw.first.Yinyinyin'

  手动翻译ing..................

  翻译完毕..................

  

  'Yinyinyin()' has private access in 'com.lxw.first.Yinyinyin',意为:构造方法Yinyinyin()在Yinyinyin类中是私有的,这就是用private修饰构造方法的问题,那就是,当你用private修饰了构造方法之后,类将不能被new。

  不能被new怎么办呢?俗话说的好,办法总比问题多,脑洞开的大,就木有什么能难得到你的问题,机智的程序媛们表示:你不让我直接调用,那我间接行了吧,于是乎就出现了getset方法(提供一个公共方法,返回类中的私有成员),just like this:

Java权限修饰符-public,private,protected_第38张图片

  这样子我们就可以获取到一个类中的私有成员了,而且,我们可以发现,我们只是在别的类中不可以new Yinyinyin,但是我们在Yinyinyin自己内部是可以new的:

Java权限修饰符-public,private,protected_第39张图片

  既然这样,我们就可以使用上面的方法,提供一个get方法,然后获取到新的对象,就ok啦!

Java权限修饰符-public,private,protected_第40张图片

Java权限修饰符-public,private,protected_第41张图片

  这个时候有人要问了,为什么要用static来修饰呢?

  emmmm..........这是因为,对象一般是存储在堆内存中的,在每一个对象new的时候,堆内存就会单独为其制定一块儿空间,然后你才可以去调用这个对象的成员。但是现在都new不出,没有为其开辟空间,是没有办法直接调用其中的成员和方法的,所以,就需要用static关键字。

  static关键字修饰的成员,JVM会在启动的时候会单独开辟一块儿静态空间,然后为这些被static修饰的成员在其中分配空间,这些成员也会被所有对象共享,所有对象都可以调用。所以,这里才会使用static。

  当你学会了上述写法,那你就学会了高端大气上档次(简单到爆炸)的单例模式,可以在对刚入门的小白装B了!当然,这只是姑且算为一个单例,单例中还分为好几种实现情况,像上面的写法就是简单的饿汉式,在实际应用中会有很多的问题,所以还有优化后的懒汉式,双重检查锁模式,静态内部类模式和枚举值模式。所以为了更好的人前显圣(ZB),大家最好还是去细致的学习一下,哈哈!

 

2.3 修饰变量

  修饰变量这一块儿没有什么好说的,其实就和上面一样,不可以直接调用,但是可以使用getset方法。

 

3.protected

  protected这个关键字,其实一般情况下是不常用的,因为它主要用于继承。在使用继承的时候,会出现以下这种情况:父类有一个变量/方法,不想给其他人调用,但是想要让自己的子类可以获取。这个时候,private、public、friendly都无法实现这种功能,所以就有了protected。被protected修饰的成员,只可以被其父类和子类还有同一包下调用。

 

3.1 修饰类

  protected修饰类的情况和private一样,都是只允许修饰内部类,话不多说,上图:

  这是一个父类FatherClass,里面有一个Gson的内部类。

Java权限修饰符-public,private,protected_第42张图片

我们再新建一个SonClass的子类,继承这个父类,然后在里面加载Gson,可以看到,是没有任何问题的:

Java权限修饰符-public,private,protected_第43张图片

  但当我们在其他类中试图加载时,就会报错:

Java权限修饰符-public,private,protected_第44张图片

  这就是protected修饰类的用法了。

 

3.2 修饰方法

  没有什么特别的问题,直接过:

  1.父类中新建getGson()方法:

Java权限修饰符-public,private,protected_第45张图片

2.其他类中无法访问

Java权限修饰符-public,private,protected_第46张图片

3.子类中可以直接访问

Java权限修饰符-public,private,protected_第47张图片

 

3.3 修饰变量

  不多说,一遍过:

1.父类中添加一个名为father的变量:

Java权限修饰符-public,private,protected_第48张图片

2.子类可以访问:

Java权限修饰符-public,private,protected_第49张图片

3.其他类中无法访问:

Java权限修饰符-public,private,protected_第50张图片

 

这就是protected的主要作用了,关于这个的知识点,其他部分就是在于继承这一块儿,这里也不多说了。

 

第一次写这么多,有什么问题大家可以评论区提出,我好做修改。

你可能感兴趣的:(Java基础,修饰符,java,public,private,protected)