1.static关键字
Java类中static可修饰成员变量,方法,构造器,初始化块,内部类(接口和枚举),被static修饰的成员是类的成员,不是某一个单例的。当系统第一次准备使用时,就会为其分配内存空间,直到该类被卸载。
典例有单例模式:饿汉式和懒汉式
示例:
public class Demo02 {
public static void main(String[] args) {
Singleton1 s11 = Singleton1.getInstance();
Singleton1 s12 = Singleton1.getInstance();
System.out.println("饿汉式: s11 == s12 " + (s11 == s12));
Singleton2 s21 = Singleton2.getInstance();
Singleton2 s22 = Singleton2.getInstance();
System.out.println("懒汉式: s21 == s22 " + (s21 == s22));
}
}
// 饿汉式:
class Singleton1 {
private static Singleton1 singleton = new Singleton1();
private Singleton1() {
}
public static Singleton1 getInstance() {
return singleton;
}
}
// 懒汉式:
class Singleton2 {
private static Singleton2 singleton = null;
public static synchronized Singleton2 getInstance() {
if (singleton == null) {
singleton = new Singleton2();
}
return singleton;
}
}
运行结果:
注意:饿汉式是线程安全的,在类创建的同时就已经创建好一个静态的对象供系统使用,以后不在改变
懒汉式如果在创建实例对象时不加上synchronized则会导致对对象的访问不是线程安全的
推荐使用第一种
2.final修饰符
final修饰的变量一般用大写作为标识符。
1)修饰成员变量:
类变量必须在静态初始化块中指定初始值或声明该类变量时指定初始值,只能两个地方的其中一个
示例变量必须在非静态初始化块、声明该示例变量或者构造器中指定初始值,只能三个地方之一
示例:
//fianl修饰非静态成员变量
public class Demo03 {
//定义时初始化
public final int A = 1;
public final int B;
public final int C;
//初始化块初始化
{
B = 2;
}
//构造函数中初始化
public Demo03(){
C = 3;
}
}
//fianl修饰静态成员变量
class Demo04{
public static final int D = 5;
public static final int E;
static {
E = 6;
}
}
2)修饰局部变量
可以在定义该局部变量的时候初始化值,如若没有初始化就可以在接下来的代码中初始化,但只能初始化一次,final修饰的参数不能代码内初始化,应该由传入的参数来初始化。
示例:
class Demo05{
//final修饰的参数由传入的参数初始化
public void math(final int F){
//final修饰的局部变量只能初始化一次
final int G;
G = 1;
}
}
3)final修饰基本类类型变量和引用变量的区别
final修饰的基本类的类型变量不可再重新赋值,但是如果是修饰引用变量,只要保证引用的地址不变即可,引用的对象完全可以改变。
示例:
public class A {
public static void main(String[] args) {
Demo06 d = new Demo06();
System.out.println(d.A);
System.out.println(d.P);
d.p.setName("小黑");//改变引用变量的属性值
System.out.println(d.p);
}
}
class Demo06 {
public final int A= 1;
public final People P;
{
P = new People("小白");
}
}
class People {
String name;
public People(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String toString() {
return "Person [name=" + name + "]";
}
}
运行结果:
4)final修饰的类
final修饰的类不能被继承,如Math类。
final class B{
}
3.抽象类
- 用abstract关键字来修饰
- 含有抽象方法的类一定是抽象类,抽象类可以不含有抽象方法
- 抽象类不能被实例化
示例:
abstract class Demo07{
public int a;//实例成员变量
public void math(){//实例方法
}
public abstract void key();//抽象方法
}
4.接口
- 接口的关键字是interfa
- 接口是比抽象类更为抽象的“抽象类”
- 接口里的所有方法都是抽象的
- 类可以多继承接口,通过关键字implements
- 接口里可以包含变量(只能是常量),方法(只能是抽象方法),内部类(包括内部接口)
示例:
interface Animal{
public static final int HEAD = 1;//成员变量必须是public static final修饰的
public abstract void math1();//抽象方法
}
5.内部类
内部类分为:静态内部类,非静态内部类、局部内部类和匿名内部类
局部内部类和匿名内部类不是类成员
内部类比外部类可以多用三个修饰符号:private 、protect、static修饰,外部类不可以使用这三个修饰符
1)非静态内部类:不可以拥有静态静态成员
访问控制符:private 同一个类
protect 父子类
default 同一个包
public 任何地方
非静态内部类是对象相关,需要通过父类对象创建
非静态内部类可以访问外部类的属性,反过来则不行
如果非静态内部类中的属性、方法名与外部类相同,则通过
外部类名.this.属性名(方法名)调用。内部则通过 this.属性名(方法名)调用
示例:
//外部类
class Outer{
private int a;
private String name;
//内部类
class inner{
private int b = a;//内部类使用外部类私有属性
private String name;
public void math(){
System.out.println("外部类的名字" + Outer.this.name);//通过类名.this调用外部类同名属性
System.out.println("内部类的名字" + this.name);
}
}
}
2)静态内部类:
- 与外部类是类相关
- 可以包含静态成员,也可以包含非静态成员
- 只能访问外部类的静态成员
- 若在接口中定义内部类,默认被public static 修饰,但意义不大
示例:
//外部类
class Outer{
private static int a;
private static String name;
//内部类
static class Inner{
private int b = a;//内部类只能调用外部静态属性
private String name;
public static int c;//可以定义静态属性
public void math(){
System.out.println("外部类的名字" + Outer.name);//通过类名调用外部类同名属性
System.out.println("内部类的名字" + this.name);
}
}
public void math(){
int e = Inner.c;//通过类名调用内部静态属性
}
}
3)局部内部类
做用不大,写在方法内
4)匿名内部类
通常是抽象类或者接口作为参数传入方法中
示例:
public class Demo08 {
/**
* @param args
*/
public static void main(String[] args) {
Eat e = new Eat();
e.eat(new Fruit() {//匿名内部类只使用一次
void shap() {
System.out.println("这事一个圆形的苹果。");
}
void color() {
System.out.println("这个苹果很红很红");
}
});
}
}
abstract class Fruit{
abstract void color();
abstract void shap();
}
class Eat{
public void eat(Fruit f){
f.color();
f.shap();
}
}
运行结果: