Java中修饰符的总结
------- android培训、java培训、期待与您交流! ----------
public/protected//private
刚开始学习会看到类、方法、变量前面有时候会写public 有时候会写private,有时候又什么都不写;会觉得很奇怪,慢慢的就懂了。
Public表示公开,private表示私有,protected表示保护,什么都不写表示默认。
方法:
如果方法前面是private,表示这个方法只能被类中内部调用,这些方法通常是为了实现其他方法的辅助方法,只为简化代码而非对外提供功能。
如果方法前面是什么都没有则可以在同一个包中的其他类调用。
如果方法前面是protected则可以由同一个包的其他类和子类调用。
如果方法前面是public则可以在类的外部调用,通常来说,作的方法都是为外部提供功能,所以多数方法都为public的。
成员变量:
考虑的安全性和健壮性的问题,成员变量一般为私有,并对外提供一些public的方法修改成员变量,在修改的方法中对输入进行判断和控制。
Private成员变量只能在类的内部使用。Public的成员变量可以在类的外部使用。
类:
类的权限修饰符只有不加和public两种。不加表示只有同一个包的类可以访问,public类所有的其他类都可以访问。
final
意为终结、中止,可以用于修饰成员变量、方法、和类。
被final修饰的变量
只能赋值一次,赋值后不能改变。这里是指指向不能改变,但指向的对象是可以改变的。
见如下代码:
class FinalDemo1{ static final Person P = new Person(5); public static void main (String[] args){ System.out.println(P.getAge()); P.setAge(10); System.out.println(P.getAge()); //如下代码不能通过编译 //P = new Person(20); } } final class Person{ private int age; Person(int age){ this.age =age; } public void setAge(int age){ this.age =age; } public int getAge(){ return this.age; } }
但成员变量和局部变量略有不同。
成员变量有默认的初始值,局部变量在定义的时候必须指定初始值。
所以,final修饰的成员变量有2种赋值机会(初始化的时候,构造对象的时候,但不能两种都用)
还有一点,final常和static一起使用,指定变量为类的常量,而且这个常量的命名通常为全字母大写。
被final修饰的类
不能被继承,同时,final类中的所有方法默认都是final的。(如下代码编译不能通过)
final class Person{ } class Student extends Person{ }
被final修饰的方法
不能被子类覆盖。如下代码不能被编译通过。
class Person{ public final void method(int i){ System.out.println(i); } } class Student extends Person{ public void method(int i){ System.out.println(i+5); } }
Static
意为静态,用于修饰成员变量、方法、代码块。
静态成员变量
静态成员变量随着类的加载而加载,多个对象共享该静态成员变量。看如下代码:
class StaticDemo1{ public static void main (String[] args){ Demo d1 = new Demo(); System.out.println("---------"); Demo d2 = new Demo(); } } class Demo{ private static int i =0; Demo(){ i++; System.out.println(i); } } 打印结果: 1 --------- 2
可以看到到静态成员变量i是多个对象共享的。
静态方法
当修饰方法的时候,这个方法随着类的加载而加载,直接通过类名来调用。很多工具类中的方法都是静态的,直接通过“类名.方法名”调用。不过静态方法中不能使用非静态成员变量和非静态方法。
静态代码块
静态代码块(java的类在产生对象的时候,在调用构造方法的时候,还会调用构造代码块)。
请看下列代码(证明构造方法、构造语句、静态构造语句运行的先后顺序):
class StaticDemo2{ public static void main (String[] args){ Demo d1 = new Demo(); System.out.println("---------"); Demo d2 = new Demo(); } } class Demo{ public Demo(){ System.out.println("构造方法"); } { System.out.println("构造代码块"); } static { System.out.println("静态构造代码块"); } } 打印结果 静态构造代码块 构造代码块 构造方法 --------- 构造代码块 构造方法
可以看到,静态代码块先执行,但只会执行一次,普通构造代码块后执行,最后执行的是构造方法。
请看下面的代码(证明类加载时,静态代码块执行):
class StaticDemo3{ public static void main (String[] args){ System.out.println(1000); System.out.println(Demo.method()); } } class Demo{ static int method(){ return 1; } static{ System.out.println("静态构造代码块"); } } 打印结果: 1000 静态构造代码块 1
需要注意的是:
java中的main方法必须写成static的,因为,在类加载时无法创建对象,静态方法可以不通过对象调用。
所以在类加载时就可以通过main方法入口来运行程序。
注意:父类中是静态方法,子类中不能覆盖为非静态方法。
在符合覆盖规则的前提下,在父子类中,父类中的静态方法可以被子类中的静态方法覆盖,但是没有多态。
使用引用调静态方法,相当于使用引用的类型去调用静态方法。(在使用对象调用态方法时其实是调用编译时类型的静态方法)
一个类在什么时候被加载?时机 (延迟加载,能不加载就不加载)
(1)new 一个对象的时候,加载
这个很好理解,不解释了。
(2)没有创建对象,访问类中静态成员(方法和属性),加载
见StaticDemo3
(3)声明一个类的引用,不加载
(4)创建子类,先加载父类,再加载子类
在继承中可以学习到。
(5)父类中的公开静态方法,子类继承,使用子类的类名调用此方法,加载父类
Abstract
这个修饰符表示抽象,可以用在方法和类前面。
抽象方法表示,类应该具备此功能,但不同的子类应该有不同的实现方式,所以没有定义具体如何做。具体如何做由子类自己实现。子类在实现所有抽象方法后才能new对象。
如有类的内部有抽象方法,则类也必须是抽象的。抽象类不能直接new对象。抽象类中可以有非抽象方法。