zoukankan      html  css  js  c++  java
  • Java 访问控制

    1.包的概念

    1)package

    • 作用:避免类的命名冲突
    • 包名可以有层次结构,类的全称:包名.类名
    • 同包中的类不能同名
    • 建议:包名所有字母都小写
    • package语句必须写在Java源文件的最开始处

    定义包名:

    package org.apache.commons.lang
    

      在实际应用中,包的命名常常是多层次的,因为如果各个公司或开发组织的程序员都随心所欲的命名包名的话,依然不能从根本上解决命名冲突的问题,不利于软件的复用。如上案例,org.apache表示公司或组织的信息(是这个公司或组织域名的反写),commons表示项目的名称信息,lang表示模块的名称信息。

    2)import

    • 同包中的类可以直接访问
    • 不同包中的类不能直接访问,若想访问有以下两种方式:
        • a.先import后在访问,import 包名.类名——建议
        • b.类的全称,包名.类名——太繁琐,不建议

    不同包的两种访问方式:

    import org.test.core.Point;
    Point p = new Point();
    或者
    org.test.core.Point p = new org.test.core.Point();
    

      有时在import语句中也可以使用“*”符号,例如:

    import org.test.core.*;
    

      如上import语句意味着该包中所有类的全称,即在该源文件中,使用所有包名为org.test.core的类都可以仅仅通过类名来访问。需要注意的是,“import 包名.*”语句并不包含该名的子包中的类(比如org.test中的类不包含)。

      Tips:在Eclipse中,可以使用“CTRL+SHIFT+O”自动完成import语句。

     

    2.访问控制修饰符

    2.1 封装的意义

    • 降低代码出错的可能性,更便于维护
    • 当内部实现细节改变时,只要保证对外的功能定义不变,其他的模块不需要更改

    2.2 访问控制修饰符

    • public:公共的,任何类
    • private:私有的,本类
    • protected:受保护的,本类、子类、同包类
    • 默认的:什么也不写,本类、同包类
    修饰符 本类 同一个包中的类 子类 其他类
    public 可以访问 可以访问 可以访问 可以访问
    protected 可以访问 可以访问 可以访问 不能访问
    默认 可以访问 可以访问 不能访问 不能访问
    private 可以访问 不能访问 不能访问 不能访问

     

     

     

     

     

      注意:类的访问控制修饰符只能是public或默认的,类中的成员变量如上4种都可以。

     

    3. static与final

    3.1 static:静态的

    3.1.1 static修饰成员变量

      static可以修饰成员变量,它所修饰的成员变量不属于对象的数据结构,而是属于类的变量,通常通过类名来引用static成员。当创建对象后,成员变量存储在堆中,而static成员变量和类的信息一起存储在方法区中,一个类的static成员变量只有“一份”(存储在方法区中),无论该类创建了多少对象。

    1)静态变量:

      1.1)由static修饰的

      1.2)属于类的,存在方法区中,只有一份

      1.3)常常通过类名.变量来访问

      1.4)何时用:所有对象所共享的数据(图片、音频、视频等)

    案例1:static修饰成员变量

    public class StaticVarDemo {
    	public static void main(String[] args){
    		Student s1 = new Student(2);
    		Student s2 = new Student(3);
    //		s1.age = 5;  编译错误,private修饰,无法访问
    	}
    }
    class Student{
    	private int age;
    	private static int numOfStudent;
    	public Student(int age){
    		this.age = age;
    		System.out.println(++numOfStudent);
    	}
    }
    

    以上代码运行结果:

    1
    2
    

    以上运行结果分析:如上代码,声明两个Student类对象后,numOfStudent的值为2。当声明第一个Student类对象后,numOfStudent值增1变为1(默认为0),声明第二个Student对象后,因为numOfStudent存在方法区中只有一份,所以其值在刚刚的1的基础上变为2。

     

    3.1.2 static修饰方法

      通常的方法都会涉及到对具体对象的操作,这些方法在调用时,需要隐式的传递对象的引用(this),而static修饰的方法则不需要对某些对象进行操作,其运行结果仅仅与输入的参数有关,调用时直接类名引用即可,如下代码:

    double c = Math.sqrt(3.0*3.0);
    

      上面的方法在调用时,没有隐式的传递对象引用,因此在static方法中是不可以使用this关键字的。另外,由于static在调用时没有具体的对象,因此在static方法中不能对非static成员(对象成员)进行访问。

      static方法的作用在于提供一些“工具方法”和“工厂方法”等,如下的一些工具方法,只是完成某一功能,不需要传递this。

    RandomUtils.nextInt()
    StringUtils.leftPad(String str,int size,char padChar)
    

     

    2)静态方法:

      2.1)由static修饰的

      2.2)属于类的,存在方法区中,只有一份

      2.3)常常通过类名.方法来访问

      2.4)静态方法没有隐式的this传递,静态方法中不能直接访问实例成员

      2.5)何时用:方法的操作仅与参数相关而与对象无关

     

    3.1.3 static块

      static块为属于类的代码块,在类加载期间执行的代码块,只执行一次,可以用来在软件中还在静态资源(图像、音频等)。

    案例2:静态块演示

    public class StaticBlockDemo {
    	public static void main(String[] args){
    		Foo foo = new Foo();
    	}
    }
    class Foo{
    	public Foo(){
    		System.out.println("Foo()");
    	}
    	static{
    		//类加载期间,只执行一次
    		System.out.println("Load Foo.class");
    	}
    }
    
    
    /*
    运行结果:
    Load Foo.class
    Foo()
     */
    

      在Foo类加载时,先运行静态块,而后执行构造方法,即:static块是在创建对象之前执行的。

     

    3)静态块:

      3.1)属于类的,在类被加载期间自动执行,因为类只被加载一次,所以静态块也只执行一次

      3.2)何时用:初始化/加载静态资源(图片、音频、视频等)

     

    3.2 final:最终的、不可变的

    • 修饰变量:变量不能被改变
    • 修饰方法:方法不能被重写
    • 修饰类:类不能被继承

    3.2.1 final修饰变量

      final关键字修饰变量,意为不可改变的,final可以修饰成员变量,也可以修饰局部变量,当final修饰成员变量时,可以有两种初始化方式:

    1. 声明同时初始化
    2. 构造函数中初始化

      final关键字修饰局部变量,在使用之前初始化即可。

    public class FinalVarDemo {
    	private final int no=100;  //final成员变量声明时初始化
    	public static void main(String[] args){
    //		no = 99;  编译错误,因为final变量不可被改变
    	}
    }
    

      

    3.2.2 final修饰方法

      final关键字修饰方法不可以被重写,使一个方法不能被重写的意义在于:防止子类在定义新方法时造成的“不经意”重写,如下案例。

    class Car{
    	//点火
    	public void fire(){...}
    }
    class Tank extends Car{
    	//开炮
    	public void fire(){...}
    }
    

      为避免上述情况,可以将Car类方法声明为final的,这样该方法就不能被子类重写。

    class Car{
    	//点火
    	public final void fire(){}
    }
    class Tank extends Car{
    	//开炮
    //	public void fire(){}  编译错误,不能被重写
    }
    

      

    3.2.3 final修饰类

      final关键字修饰的类不可以被继承。使一个类不能被继承的意义在于:可以保护类不被继承修改,可以控制滥用继承对系统造成的危害。在JDK中的一些基础类库被定义为final的,如:String、Math、Integer、Double等。自己定义的类也可以声明为final的。

    final class Foo{}
    class Goo extends Foo{}  //编译错误,final修饰的类不可以被继承
    

      

    3.3 static final常量

    • 必须声明同时初始化
    • 通过类名来访问,不能被改变
    • 常量名所有的字母都大写,多个单词用_分隔(如STUDENT_NAME)
    • 编译器在编译时会将常量直接替换为具体的值,效率高
    public class FinalFunctionDemo {
    	public static void main(String[] args){
    		System.out.println(Soo.NUM);   //使用类名. 来访问
    		//代码编译时,会替换为:System.out.println(100);
    	}
    }
    
    class Soo{
    	public static final int NUM=100;
    }
    
    
    //运行结果:100
    

      

    4. 案例演示

    案例3:final演示

    //演示final修饰变量
    /*
     * final 修饰成员变量,只有两种初始化方法:
     * 1)声明的同时初始化
     * 2)在构造方法中初始化
     * final修饰局部变量,只要在用之前初始化即可
     */
    class Aoo{
    	final int a = 5;
    	final int b;
    	Aoo(){
    		b = 6;
    	}
    	void show(){
    		final int c;
    //		a = 55; //编译错误,final的变量不可被改变
    	}
    }
    
    //演示final修饰方法
    class Boo{
    	final void show(){}
    	void say(){}
    }
    class Coo extends Boo{
    //	void show(){}  //编译错误,final修饰的方法不能被重写
    	void say(){}
    }
    
    //演示final修饰类
    final class Doo{
    
    }
    //class Eoo extends Doo{}  //编译错误,final修饰的类不能被继承
    class Foo{}
    final class Goo extends Foo{} //final修饰的类可以继承别的类
    

    案例4:static演示

    public class StaticDemo {
    	public static void main(String[] args){
    		Joo o1 = new Joo();
    		o1.show();
    		/*
    		输出:
    		a=1
    		b=1
    		*/
    		
    		Joo o2 = new Joo();
    		o2.show();
    		System.out.println("Joo.b="+Joo.b);  //建议类名. 来访问
    		System.out.println("o1.b="+o1.b);    //不建议
    		System.out.println("o2.b="+o2.b);     //不建议
    		/*
    		 *输出:
    		 *a=1
    		 *b=2
    		 *Joo.b=2
    		 *o1.b=2
    		 *o2.b=2
    		*/
    		
    		Koo.test();
    		/*
    		 * 输出:
    		 * 0
    		 */
    		
    		Loo o3 = new Loo();
    		Loo o4 = new Loo();
    		/*
    		 * 输出:
    		 * 静态块 //静态块只执行一次
    		 *构造方法
    		 *构造方法
    		 */
    	}
    }
    class Loo{  //演示静态块
    	static{
    		System.out.println("静态块");
    	}
    	Loo(){
    		System.out.println("构造方法");
    	}
    }
    
    class Koo{  //演示静态方法
    	int a;
    	static int b;
    	void show(){   //有隐式this
    		System.out.println(a);   //this.a
    		System.out.println(b);   //Koo.b
    	}
    	static void test(){  //没有隐式this
    		/*没有this意味着没有对象,而实例成员必须通过对象. 来访问
    		所以静态方法中不能直接访问实例成员
    		System.out.println(a);  编译错误
    		*/
    		System.out.println(b);  //Koo.b
    	}
    }
    class Joo{  //演示静态变量
    	int a;  //实例变量
    	static int b;  //静态变量
    	Joo(){
    		a++;
    		b++;
    	}
    	void show(){
    		System.out.println("a="+a);
    		System.out.println("b="+b);
    	}
    }
    
    /*
    输出结果:
    a=1
    b=1
    a=1
    b=2
    Joo.b=2
    o1.b=2
    o2.b=2
    0
    静态块
    构造方法
    构造方法
    */
    

      

    案例5:static final的演示

    public class StaticFinalDemo {
    	public static void main(String[] args){
    		System.out.println(Hoo.PI);  //3.14  通过类名点 来访问
    //		Hoo.PI = 3.1415926; //编译错误,常量不能被改变
    		
    		Ioo o1 = new Ioo();
    		o1.count = 50;
    		Ioo o2 = new Ioo();
    		System.out.println(o2.count);  //50 静态变量只有一份
    		
    		/*
    		 * 1)加载Ioo.class到方法区中
    		 * 2)静态变量count存储到方法区中
    		 * 3)到方法区中获取count并输出
    		 */
    		System.out.println(Ioo.count);
    		
    		/*
    		 * 编译器在编译时会将常量直接替换为具体的值---效率高
    		 */
    		System.out.println(Ioo.NUM);  //5
    	}
    }
    class Ioo{
    	public static final int NUM = 5; //常量
    	public static int count = 5;  //静态变量
    }
    class Hoo{
    	public static final double PI = 3.14;
    	public static final int DOUBLE_NUM = 5;
    //	public static final int NUMBER; //编译错误,常量必须声明并初始化
    }
    

      

     

     

     

  • 相关阅读:
    Netsharp下微信菜单以及OAuth
    权限管理
    java面向对象基础(转)
    闲来无事做了一个批处理的win10账号管理
    bat获取系统时间修改系统密码
    bat常用命令
    bat修改密码
    vbs的一些入门基础。。。
    WCF 之 DataContract
    WCF 之 OperationContract
  • 原文地址:https://www.cnblogs.com/jmwm/p/7004545.html
Copyright © 2011-2022 走看看