面向对象三


1.关键字static

  • 用static修饰的属性称为类属性,类属性是对象共享的
  • static可以用来修饰属性、方法、代码块、内部类
  • 被static修饰的成员有以下特点:
    1. 随着类单独加载而加载
    2. 优先于对象存在
    3. 修饰的成员被所有对象共享
    4. 可以不用创建对象而直接被类调用
    5. 类变量类加载以后存在于方法区,不和对象一起存在于栈区
    6. 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);//第一个对象修改  第二个对象也受影响  因为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;
}
}
  • 成员变量的赋值顺序
    1. 声明成员变量的默认初始化
    2. 显示初始化(静态代码块或非静态代码块初始化)
    3. 构造器对成员变量初始化
    4. 创建对象以后,使用对象.属性或对象.方法再次赋值
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++;   wrong
          return x+1;  // right
      }
      public void addOne(final Other o)
      {
        // o=new Other();  wrong
        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不支持多继承,而接口可以实现多继承的效果
  • 继承是一个“是不是”的关系,接口是一个“能不能”的关系
  • 接口的本质是契约、标准、规范
  • 接口特点:
    1. 用interface定义
    2. 接口中所有的成员变量默认由public static final修饰
    3. 接口中所有的抽象方法默认由public abstract修饰
    4. 接口中没有构造器(抽象类中可以有)
    5. 接口也可以继承接口,用extends
    6. 实现接口的类必须要提供接口中所有方法的具体实现内容
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.接口和抽象类的比较

区别抽象类接口
组成构造方法 抽象方法 普通方法 常量 变量常量 抽象方法
使用extendsimplements
关系抽象类可以实现多个接口接口不能继承抽象类,只能继承多个接口
局限只能单继承可以实现多个接口
  • 使用接口和抽象类的几个注意点:
    1. 如果接口和抽象类中有着相同的方法或属性,而子类又继承了该类并且实现了接口,则优先使用类中的变量
    2. 如果两个或以上接口中有着重名的方法或属性,需要用接口名.属性或接口名.方法指定是哪一个
    3. 如果右两个接口,一个接口中有一个默认方法,另一个接口中也有一个相同的方法,不考虑默认还是不默认,子类必须重该方法,否则会出现冲突
interface A{
    public void m();
    
}
interface B{
    public default void m(){
        System.out.println("m in B");
    }
}
class C implements A,B{
    //这里需要出现m方法,不然会报错
}
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);//局部变量形参s
            System.out.println(this.s);//内部类对象的s
            System.out.println(Outer.this.s);//外部类对象的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类型的对象
    {
        a.fun1();
    }
}
interface A{
    public abstract void fun1();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodePanda@GPF

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值