访问修饰符
访问控制修饰符定义类、变量、方法的访问权限。Java支持4种访问控制修饰符:public, protected, default, private.
/**
* @author: 毛利
*/
public class Demo1 {
// static ,非访问修饰符,静态变量;final,非访问修饰符,使变量不可变,结合static就成了常量
private static final int NUM1 = 1;
public static final int NUM2 = 2;
protected static final int NUM3 = 3;
static final int NUM4 = 4;
public static void main(String[] args) {
System.out.println(NUM1);
System.out.println(NUM2);
System.out.println(NUM3);
System.out.println(NUM4);
}
}
/**
* @author: 毛利
*/
public class Demo2 extends Demo1 {
public static void main(String[] args) {
// System.out.println(NUM1); 报错 无法访问
System.out.println(NUM2);
System.out.println(NUM3);
System.out.println(NUM4);
}
}
/**
* @author: 毛利
*/
public class Demo3 extends Demo1 {
public static void main(String[] args) {
// System.out.println(NUM1);
System.out.println(NUM2);
System.out.println(NUM3);
// System.out.println(NUM4); //报错
}
}
重点: 父类中声明为 public 的方法在子类中也必须为 public。 父类中声明为 protected 的方法在子类中要么声明为 protected,要么声明为 public,不能声明为 private。 父类中声明为 private 的方法,不能够被继承
/**
* @author: 毛利
*/
public class Demo4 {
public static void main(String[] args) {
Demo1 demo1 = new Demo1();
System.out.println(demo1.NUM2);
// System.out.println(demo1.NUM3); 报错
// System.out.println(demo1.NUM4); 报错
}
}
首先,了解下成员变量
成员变量可以分为:
一种是被static关键字修饰的变量,叫类变量或者静态变量, 另一种没有static修饰,为成员变量,是通过创建对象来访问
/**
* @author: 毛利
*/
public class Demo5 {
static final int num1 = 1;
int num2;
Demo5(){
this.num2 = 2;
}
public static void main(String[] args) {
System.out.println(" 静态变量 num1=" + Demo5.num1);
Demo5 demo5 = new Demo5();
System.out.println("实例变量 num2=" + demo5.num2);
}
}
补充局部变量
局部变量:形参、方法内定义的变量、代码块中定义的变量,都属于局部变量。
静态变量属于整个类所有,而不是某个对象所有,即被类的所有对象共享。
补充:JAVA中初始化的顺序:
/**
* @author: 毛利
*/
public class Demo6 {
// 静态变量
// 2.第二步,静态变量和静态代码块的加载顺序由编写先后决定
static int num = 4;
// 静态块
static {
System.out.println("开始执行静态代码块");
// 3.第三步,静态块,然后执行静态代码块,因为有输出,故打印a
System.out.println("a");
System.out.println(num);
}
public static void main(String[] args) {
System.out.println("开始创建类");
//4.第四步,new一个类,但在new之前要处理匿名代码块
new Demo6();
}
// 匿名代码块
{
System.out.println("开始加载匿名代码块");
num += 3;
//5.第五步,按照顺序加载匿名代码块,代码块中有打印
System.out.println("b");
System.out.println(num);
}
//6.第六步,按照顺序加载变量
int a = 5;
// 按照顺序加载匿名代码块 匿名代码块本身就是成员变量
{
//7.第七步,按照顺序打印c
System.out.println("c");
}
// 类的构造函数,第四个加载
Demo6() {
//8.第八步,最后加载构造函数,完成对象的建立
System.out.println("d");
System.out.println(a);
}
// 静态方法,调用的时候才加载
static void run()
{
// 静态方法没有执行
System.out.println("e");
}
}
static是静态修饰符,什么叫静态修饰符呢?在程序中任何变量或者代码都是在编译时由系统自动分配内存来存储的,而所谓静态就是指在编译后所分配的内存会一直存在,直到程序退出内存才会释放这个空间,也就是只要程序在运行,那么这块内存就会一直存在。
在Java程序里面,所有的东西都是对象,而对象的抽象就是类,对于一个类而言,如果要使用他的成员,那么普通情况下必须先实例化对象后,通过对象的引用才能够访问这些成员,但是有种情况例外,就是该成员是用static声明
/**
* @author: 毛利
*/
public class Demo7 {
/*
总结如下
static修饰静态方法:
会使得这个方法成为整个类所共有的方法,可以用“类名.方法名”访问。
static修饰的方法,不能直接访问本类中非静态成员,但是本类中的非静态方法可以访问静态成员。
在静态方法中不能出现this关键字。
Java中的main方法必须写成static的原因:在类加载时无法创建对象,而静态方法可以不通过对象调用,所以在类加载时就可以通过main方法入口来运行程序。
*/
int num1 = 1;
static int num2 = 2;
// 静态demo方法
static void demo(){
// System.out.println("num1="+num1); 报错
// 因为静态demo方法不能使用非静态成员num1
System.out.println("num2"+num2);
}
public void demo1(){
//但是本类中的非静态方法可以访问静态成员
System.out.println(num1);
System.out.println(num2);
}
public static void main(String args[]){
// 执行静态demo方法
demo();
// demo1() 报错
/*
因为对于一个类而言,如果要使用他的成员,那么普通情况下必须先实例化对象后,通过对象的引用才能够访问这些成员
*/
Demo7 demo7 = new Demo7();
System.out.println("执行demo1方法 ");
demo7.demo1();
}
// 一旦类被加载,所有的static语句被运行。
static{
System.out.println("demo7类被加载");
num2 = num2 + 1 ;
// num2 = 3
}
}
final修饰类即表示此类已经是“最后的、最终的”含义。
因此,用final修饰的类不能被继承,即不能拥有自己的子类。
public final class Demo8 {}
public class Demo9 extends Demo8{} // 报错
final修饰的变量值也不可被改变。
final 方法可以被子类继承,但是不能被子类重写。
final 修饰符通常和 static 修饰符一起使用来创建类常量。
/**
* @author: 毛利
*/
public class Demo8 {
final int num1 = 1;
{
// num1 +=1 ; // 报错
//System.out.println(num1);
}
// public static final 通常创建静态变量 一般要大写
public static final int NUM2 = 2;
public static void main(String[] args) {
String a = "Maoli";
final String b = "Mao";
String d = "Mao";
String c = b + "li";
String e = d + "li";
System.out.println((a == c)); // true
// 在编译期间能知道b的确切值,则编译器会把它当做编译期常量使用
// 直接访问的这个常量,不需要在运行时确定 编译器进行了优化
System.out.println((a == e)); // false
//基本数据类型
final int i = 1;
//引用类型,引用test类
final Test t = new Test("Maoli今年20年,专业化工");
System.out.println(t.getStr());
// 重新setStr的值,没问题,说明变量本身指向的对象的值可以改变
t.setStr("谁说不是计算机的不会Java?");//
System.out.println(t.getStr());
//试着重新new一个test给t对象,
t = new Test("重新new一个test给t对象,竟然报错了");
//变量的引用不可以改变
}
}
class Test{
private String str;
public Test(String str) {
this.str = str;
}
public String getStr() {
return str;
}
public void setStr(String a) {
this.str = a;
}
}
abstract 抽象
这个类成为一个抽象类,这个类将不能生成对象实例
一个类不能同时被 abstract 和 final 修饰。子类继承并覆盖其中的抽象方法。
/**
* @author: 毛利
*/
public abstract class Demo9{
String name = "maoli";
String year = "199910";
public abstract void getname(); //抽象方法
public abstract void getyear();
private void print111(){
System.out.println(111);
}
public void print222(){
System.out.println(222);
}
}
class Maoli extends Demo9{
// 需要子类继承并覆盖其中的抽象方法。
@Override
public void getname() {
System.out.println("我的网名: "+ name);
}
@Override
public void getyear() {
System.out.println("我的出生年月" + year);
}
public static void main(String[] args) {
Maoli maoli = new Maoli();
maoli.getname();
maoli.getyear();
}
}
synchronized 和 volatile 修饰符主要用于线程的编程。
volatile是轻量级的synchronized,在多处理器(多线程)开发中保证了共享变量的“可见性”。
可见性表示当一个线程修改了一个共享变量时,另外一个线程能读到这个修改的值。
由于涉及Java多线程,篇幅难度更大,本文先断