1.关键字static
- 用static修饰的属性称为类属性,类属性是对象共享的
- static可以用来修饰属性、方法、代码块、内部类
- 被static修饰的成员有以下特点:
- 随着类单独加载而加载
- 优先于对象存在
- 修饰的成员被所有对象共享
- 可以不用创建对象而直接被类调用
- 类变量类加载以后存在于方法区,不和对象一起存在于栈区
- static修饰的方法中不能出现this,super关键字 因为它不属于对象
public class test {
public static void main(String[] args) {
StaticDemo staticDemo1=new StaticDemo();
StaticDemo staticDemo2=new StaticDemo();
System.out.println(staticDemo1.s);
System.out.println(StaticDemo.s);
staticDemo1.s="我修改了静态变量";
System.out.println(staticDemo2.s);
}
}
class StaticDemo{
static String s="我是静态变量";
}
我是静态变量
我是静态变量
我修改了静态变量
2.单例设计模式
public class test {
public static void main(String[] args) {
Singleton singleton=Singleton.getSingleton();
}
}
class Singleton{
private Singleton()
{
}
private static Singleton singleton=new Singleton();
public static Singleton getSingleton()
{
return singleton;
}
}
public class test {
public static void main(String[] args) {
Singleton singleton=Singleton.getSingleton();
}
}
class Singleton{
private Singleton()
{
}
private static Singleton singleton;
public static Singleton getSingleton()
{
if(singleton==null)
singleton=new Singleton();
return singleton;
}
}
3.代码块
- 代码块可以对Java类或对象进行初始化
- 有static修饰的是静态代码块 没有static修饰的是非静态代码块
- static代码块一般用于初始化static的属性
class Person{
public static int total;
static{
total=100;
}
}
- 成员变量的赋值顺序
- 声明成员变量的默认初始化
- 显示初始化(静态代码块或非静态代码块初始化)
- 构造器对成员变量初始化
- 创建对象以后,使用对象.属性或对象.方法再次赋值
class Value{
int value=0;
{
value=1;
}
public Value()
{
value=2;
}
public void setValue()
{
value=3;
}
}
4.final
- final标记的类不能被继承 比如String System StringBuffer
- final标记的方法不能被子类重写
- final标记的变量称为常量,只能被赋值一次,必须显示初始初始化(声明时、代码块、构造器)
class Value{
final int VALUE=1;
}
class Value{
final int VALUE;
{
VALUE=1;
}
}
class Value{
final int VALUE;
public Value()
{
VALUE=1;
}
}
- 被final修饰的基本类型不能改变,被fianl修饰的引用类型地址也不能改变,但是可以改变引用的对象的内容
public class test {
public static void main(String[] something_to_do) {
}
public int addOne(final int x)
{
return x+1;
}
public void addOne(final Other o)
{
o.i++;
}
}
class Other{
public int i;
}
5. 抽象类与抽象方法
- 用abstract修饰的类叫做抽象类
- 用abstract修饰方法叫做抽象方法
- 含有抽象方法的类必须被声明为抽象类
- 抽象类不能被实例化
- 抽象类是用来继承的,继承抽象类的子类必须重写父类的抽象方法
- 不能用abstrat修饰变量、代码块、构造器(构造器不能被继承)
- 不能用abstrac修饰私有方法(不能被继承)、静态方法、final方法(不能被改写)
public class test {
public static void main(String[] something_to_do) {
A a=new B();
a.m1();
a.m2();
}
}
abstract class A{
abstract void m1();
public void m2()
{
System.out.println("A类中的m2方法");
}
}
class B extends A{
void m1(){
System.out.println("B类中定义的m1方法");
}
}
B类中定义的m1方法
A类中的m2方法
6.接口
- 由于Java不支持多继承,而接口可以实现多继承的效果
- 继承是一个“是不是”的关系,接口是一个“能不能”的关系
- 接口的本质是契约、标准、规范
- 接口特点:
- 用interface定义
- 接口中所有的成员变量默认由public static final修饰
- 接口中所有的抽象方法默认由public abstract修饰
- 接口中没有构造器(抽象类中可以有)
- 接口也可以继承接口,用extends
- 实现接口的类必须要提供接口中所有方法的具体实现内容
public class test {
public static void main(String[] something_to_do) {
Person stu=new Student();
stu.say();
stu.run();
stu.sleep();
}
}
interface Person{
public void say();
public void run();
public void sleep();
}
class Student implements Person{
@Override
public void say() {
System.out.println("say");
}
@Override
public void run() {
System.out.println("run");
}
@Override
public void sleep() {
System.out.println("sleep");
}
}
interface Chinese extends Person{
}
7.接口和抽象类的比较
区别 | 抽象类 | 接口 |
---|
组成 | 构造方法 抽象方法 普通方法 常量 变量 | 常量 抽象方法 |
使用 | extends | implements |
关系 | 抽象类可以实现多个接口 | 接口不能继承抽象类,只能继承多个接口 |
局限 | 只能单继承 | 可以实现多个接口 |
- 使用接口和抽象类的几个注意点:
- 如果接口和抽象类中有着相同的方法或属性,而子类又继承了该类并且实现了接口,则优先使用类中的变量
- 如果两个或以上接口中有着重名的方法或属性,需要用接口名.属性或接口名.方法指定是哪一个
- 如果右两个接口,一个接口中有一个默认方法,另一个接口中也有一个相同的方法,不考虑默认还是不默认,子类必须重该方法,否则会出现冲突
interface A{
public void m();
}
interface B{
public default void m(){
System.out.println("m in B");
}
}
class C implements A,B{
}
interface Filial{
default void help()
{
System.out.println("help mother");
}
}
interface Spoony{
default void help()
{
System.out.println("help wife");
}
}
class Man implements Filial,Spoony{
public void help()
{
Filial.super.help();
Spoony.super.help();
}
}
8.内部类
- 定义在一个类内部的类称为内部类
- 内部类的名字不能与外部类的名字相同
- 内部类分为成员内部类和局部内部类
class Outer{
private int s;
public class Inner{
public void mb()
{
s=100;
System.out.println("内部类中s="+s);
}
}
public void ma()
{
Inner i=new Inner();
i.mb();
}
}
public class test {
public static void main(String[] something_to_do) {
Outer a=new Outer();
Outer.Inner b=a.new Inner();
b.mb(333);
new Outer().new Inner().mb(333);
}
}
class Outer{
private int s=111;
public class Inner{
private int s=222;
public void mb(int s)
{
System.out.println(s);
System.out.println(this.s);
System.out.println(Outer.this.s);
}
}
}
- 局部内部类只能在方法或代码块中使用
- 必须先声明后使用
- 局部内部类和局部变量类似,不能使用访问修饰符修饰
public class test {
public static void main(String[] something_to_do) {
Outer outer=new Outer();
Outer.Inner1 innenr1=outer.new Inner1();
innenr1.say();
outer.createInner();
}
}
class Outer{
private int s=111;
public class Inner1{
public void say()
{
System.out.println("我是成员内部类Inner1");
}
}
{
class Inner2{
public void say()
{
System.out.println("我是代码块中局部内部类Inne2");
}
}
new Inner2().say();
}
public void createInner()
{
class Inner3{
public void say()
{
System.out.println("我是方法中局部内部类Inne3");
}
}
new Inner3().say();
}
}
是代码块中局部内部类Inne2
我是成员内部类Inner1
我是方法中局部内部类Inne3
- 匿名内部类
- 区别于匿名类 new Test().test();这种叫做匿名类 不创建引用变量
- 匿名内部类必须实现父类或实现接口
- 匿名内部类只能有一个对象
- 匿名内部类只能以多态形式引用
public class Outer {
public static void main(String[] args) {
new Outer();
new Outer().calliInner(new A(){
public void fun1()
{
System.out.println("implementd for fun1");
}
});
}
public void calliInner(A a)
{
a.fun1();
}
}
interface A{
public abstract void fun1();
}