Java面向对象编程(static、单例模式、main、final、代码块、抽象类、接口、内部类)

 

static关键词


static关键字:可以修饰属性、方法、代码块、内部类。

一、使用static修饰属性:静态变量(或类变量)

  1. 属性,按是否使用static修饰,又分为:静态属性 vs 非静态属性(实例变量)
  实例变量:我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性。当修改其中一个对象中的非静态属性时,不会导致其他对象中同样的属性值的修改。
  静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量。当通过某一个对象修改静态变量时,会导致其他对象调用此静态变量时,是修改过了的。
  2. static修饰属性的其他说明:
  ① 静态变量随着类的加载而加载。可以通过"类.静态变量"的方式进行调用
  ② 静态变量的加载要早于对象的创建
  ③ 由于类只会加载一次,则静态变量在内存中也只会存在一份:存在方法区的静态域中。
  ④      类变量  实例变量
  类    yes    no
  对象   yes    yes

 

二、用static修饰方法:静态方法

  ① 随着类的加载而加载,可以通过"类.静态方法"的方式进行调用
  ②      静态方法     非静态方法
  类    yes     no
  对象    yes    yes
  ③ 静态方法中,只能调用静态的方法或属性
  非静态方法中,既可以调用非静态的方法或属性,也可以调用静态的方法或属性

三、 static注意点:
   5.1 在静态的方法内,不能使用this关键字、super关键字
   5.2 关于静态属性和静态方法的使用,大家都从生命周期的角度去理解。

 

四、 开发中,如何确定一个属性是否要声明为static的?

   > 属性是可以被多个对象所共享的,不会随着对象的不同而不同的。
   > 类中的常量也常常声明为static


  开发中,如何确定一个方法是否要声明为static的?
  > 操作静态属性的方法,通常设置为static的
  > 工具类中的方法,习惯上声明为static的。 比如:Math、Arrays、Collections

 

单例 (Singleton)设计模式
的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例
package com.atguigu.java2;
/*
 * 单例设计模式:
 * 1. 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例。
 * 
 * 2. 如何实现?
 *      饿汉式  vs 懒汉式
 * 
 * 3. 区分饿汉式 和 懒汉式
 *   饿汉式:    
 *       坏处:对象加载时间过长。
 *       好处:饿汉式是线程安全的
 *   
 *   懒汉式:好处:延迟对象的创建。
 *           目前的写法坏处:线程不安全。--->到多线程内容时,再修改
 * 
 * 
 */
public class SingletonTest1 {
    public static void main(String[] args) {
//        Bank bank1 = new Bank();
//        Bank bank2 = new Bank();
        
        Bank bank1 = Bank.getInstance();
        Bank bank2 = Bank.getInstance();
        
        System.out.println(bank1 == bank2);
    }
}

//饿汉式
class Bank{
    
    //1.私有化类的构造器
    private Bank(){
        
    }
    
    //2.内部创建类的对象
    //4.要求此对象也必须声明为静态的
    private static Bank instance = new Bank();
    
    //3.提供公共的静态的方法,返回类的对象
    public static Bank getInstance(){
        return instance;
    }
}
单例模式的饿汉式实现
/*
 * 单例模式的懒汉式实现
 * 
 */
public class SingletonTest2 {
    public static void main(String[] args) {
        
        Order order1 = Order.getInstance();
        Order order2 = Order.getInstance();
        
        System.out.println(order1 == order2);
        
    }
}


class Order{
    
    //1.私有化类的构造器
    private Order(){
        
    }
    
    //2.声明当前类对象,没有初始化
    //4.此对象也必须声明为static的
    private static Order instance = null;
    
    //3.声明public、static的返回当前类对象的方法
    public static Order getInstance(){
        
        if(instance == null){
            
            instance = new Order();
            
        }
        return instance;
    }
    
}
单例模式的懒汉式实现
单例模式的优点:由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。

 

 

 

 

main方法是静态的


 main()方法的使用说明:

  1. main()方法作为程序的入口
  2. main()方法也是一个普通的静态方法
  3. main()方法可以作为我们与控制台交互的方式。(之前:使用Scanner)

public static void main(String[] args) {}
/*
public : 被jvm调用,访问权限足够大。
static : 被jvm调用,不用创建对象,直接类名访问
void : 被jvm调用,不需要给jvm返回值
main : 一个通用的名称,虽然不是关键字,但是被jvm识别
String[] args : 以前用于接收键盘录入的
*/

 

 

代码块


类的成员之四:代码块(或初始化块)
一、代码块的作用:用来初始化类、对象
二、代码块如果有修饰的话,只能使用static.
三、分类:静态代码块 vs 非静态代码块


四、静态代码块
   >内部可以有输出语句
  >随着类的加载而执行,而且只执行一次
  >作用:初始化类的信息
  >如果一个类中定义了多个静态代码块,则按照声明的先后顺序执行
  >静态代码块的执行要优先于非静态代码块的执行
  >静态代码块内只能调用静态的属性、静态的方法,不能调用非静态的结构
  
五、 非静态代码块
  >内部可以有输出语句
  >随着对象的创建而执行
   >每创建一个对象,就执行一次非静态代码块
   >作用:可以在创建对象时,对对象的属性等进行初始化
   >如果一个类中定义了多个非静态代码块,则按照声明的先后顺序执行
   >非静态代码块内可以调用静态的属性、静态的方法,或非静态的属性、非静态的方法
  

代码块:使用 {} 括起来的代码被称为代码块,根据其位置和声明的不同,可以分为局部代码块,构造代码块,静态代码块,同步代码块(多线程讲解)。

一、局部代码块:在方法中出现;限定变量生命周期,及早释放,提高内存利用率

二、构造代码块:在类中方法外出现;多个构造方法方法中相同的代码存放到一起,每次调用构造都执行,并且在构造方法前执行。

  执行顺序:局部代码块——>静态代码块(static)——>构造代码块——>构造方法

  如果代码块中包含static,无论是在父类还是子类中,都先执行静态代码块。

  静态代码块只执行一次。

 

三、静态代码块:在类中方法外出现,加了static修饰 在类中方法外出现,并加上static修饰;用于给类进行初始化,在加载的时候就执行,并且值执行一次。

 

 

对属性可以赋值的位置:
   ①默认初始化
   ②显式初始化/⑤在代码块中赋值
   ③构造器中初始化
   ④有了对象以后,可以通过"对象.属性"或"对象.方法"的方式,进行赋值

  执行的先后顺序:① - ② / ⑤ - ③ - ④

 

 

final关键字


 final 可以用来修饰: 类、方法、变量。

  1. final关键字修饰类:类不能被其他类继承。 

    比如:String类、System类、StringBuffer类。

  2. final关键字修饰成员变量,成员变量变成了一个常量,只能赋值一次,不能被修改。                          可以考虑赋值的位置有:显式初始化、代码块中初始化、构造器中初始化
  3. final修饰局部变量,在方法内部(基本数据类型),值不能修改。如果修饰引用数据类型,引用的地址值不能发生改变(例:final  Student  s = new Studen(); )。
  4. final关键字修饰方法,方法不能被重写。比如:Object类中getClass();
  5. final初始化时机:在构造对象完成之前。
  6. static final  用来修饰属性:全局常量

 

 

抽象类


一、抽象类格式:

abstract  class  类名{}
/*
用abstract关键字来修饰一个类,这个类叫做抽象类。
用abstract来修饰一个方法,该方法叫做抽象方法。
public abstract void example();
*/

二、注意事项:

  1.抽象类不一定有抽象方法,包含抽象方法的类一定是抽象类。

  2.抽象类不能实例化,但是可以通过子类继承,通过子类实例化。抽象类的子类必须重写父类的抽象方法,并提供方法体。若没有重写全部的抽象方法,仍为抽象类。

  3.abstract 不能用来修饰 final 、final的类、private(私有方法)、static(静态方法)

  4.abstract不能用来修饰变量、代码块、构造器;

public class AbstractTest2 {
        public static void main(String args[]) {
            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方法
抽象类举例
问题1:为什么抽象类不可以使用final关键字声明?
因为抽象类得通过子类继承,子类实例化,而final关键字就指定了类不能被继承。


问题2:一个抽象类中可以定义构造器吗?
可以
抽象类思考问题

三、抽象类的匿名子类

//创建了一匿名子类的对象:p
        Person p = new Person(){
//Person类是抽象类,不可以造对象,但是通过匿名子类,需要重写抽象类中的抽象方法。

            @Override
            public void eat() {
                System.out.println("吃东西");
            }

            @Override
            public void breath() {
                System.out.println("好好呼吸");
            }
            
        };
        
        method1(p);
        System.out.println("********************");
        //创建匿名子类的匿名对象
        method1(new Person(){
            @Override
            public void eat() {
                System.out.println("吃好吃东西");
            }

            @Override
            public void breath() {
                System.out.println("好好呼吸新鲜空气");
            }
        });
    }
public static void method1(Person p){
        p.eat();
        p.breath();
    }
    
抽象类的匿名子类

 

 

 

 

接口(interface)


一、接口的使用
  1.接口使用interface来定义
  2.Java中,接口和类是并列的两个结构
  3.如何定义接口:定义接口中的成员

3.1 JDK7及以前:只能定义全局常量和抽象方法
>全局常量:public static final的.但是书写时,可以省略不写
>抽象方法:public abstract的

3.2 JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法(略)
public interface CompareA {
    
    //静态方法
    public static void method1(){
        System.out.println("CompareA:北京");
    }
    //默认方法
    public default void method2(){
        System.out.println("CompareA:上海");
    }
    
    default void method3(){
        System.out.println("CompareA:上海");
    }
}


//文件二
public class SubClassTest {
    
    public static void main(String[] args) {
        SubClass s = new SubClass();
        
//        s.method1();
//        SubClass.method1();
        //知识点1:接口中定义的静态方法,只能通过接口来调用。
        CompareA.method1();
        //知识点2:通过实现类的对象,可以调用接口中的默认方法。
        //如果实现类重写了接口中的默认方法,调用时,仍然调用的是重写以后的方法
        s.method2();
        //知识点3:如果子类(或实现类)继承的父类和实现的接口中声明了同名同参数的默认方法,
        //那么子类在没有重写此方法的情况下,默认调用的是父类中的同名同参数的方法。-->类优先原则
        //知识点4:如果实现类实现了多个接口,而这多个接口中定义了同名同参数的默认方法,
        //那么在实现类没有重写此方法的情况下,报错。-->接口冲突。
        //这就需要我们必须在实现类中重写此方法
        s.method3();
        
    }
    
}

class SubClass extends SuperClass implements CompareA,CompareB{
    
    public void method2(){
        System.out.println("SubClass:上海");
    }
    
    public void method3(){
        System.out.println("SubClass:深圳");
    }
    
    //知识点5:如何在子类(或实现类)的方法中调用父类、接口中被重写的方法
    public void myMethod(){
        method3();//调用自己定义的重写的方法
        super.method3();//调用的是父类中声明的
        //调用接口中的默认方法
        CompareA.super.method3();
        CompareB.super.method3();
    }
}
JDK8中定义的静态方法。默认方法

 



4. 接口中不能定义构造器的!意味着接口不可以实例化

5. Java开发中,接口通过让类去实现(implements)的方式来使用.
如果实现类覆盖了接口中的所有抽象方法,则此实现类就可以实例化
如果实现类没有覆盖接口中所有的抽象方法,则此实现类仍为一个抽象类

6. Java类可以实现多个接口 --->弥补了Java单继承性的局限性
格式:class AA extends BB implements CC,DD,EE

7. 类与类:继承关系。只能单继承。不能一次性继承多个,但可以多层继承。
  接口与接口之间可以继承,而且可以多继承
  类与接口:类可以单个实现接口,也可以一次性实现多个接口。可以在继承一个类时,实现多个接口,每个类都默认继承Object类。


*******************************
8. 接口的具体使用,体现多态性
9. 接口,实际上可以看做是一种规范

面试题:抽象类与接口有哪些异同?
 
public class InterfaceTest {
    public static void main(String[] args) {
        System.out.println(Flyable.MAX_SPEED);
        System.out.println(Flyable.MIN_SPEED);
//        Flyable.MIN_SPEED = 2;
        
        Plane plane = new Plane();
        plane.fly();
    }
}


interface Flyable{
    
    //全局常量
    public static final int MAX_SPEED = 7900;//第一宇宙速度
    int MIN_SPEED = 1;//省略了public static final
    
    //抽象方法
    public abstract void fly();
    //省略了public abstract
    void stop();
    
    
    //Interfaces cannot have constructors
//    public Flyable(){
//        
//    }
}

interface Attackable{
    
    void attack();
    
}

class Plane implements Flyable{

    @Override
    public void fly() {
        System.out.println("通过引擎起飞");
    }

    @Override
    public void stop() {
        System.out.println("驾驶员减速停止");
    }
    
}

abstract class Kite implements Flyable{

    @Override
    public void fly() {
        
    }
    
}

class Bullet extends Object implements Flyable,Attackable,CC{

    @Override
    public void attack() {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void fly() {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void stop() {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void method1() {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void method2() {
        // TODO Auto-generated method stub
        
    }
    
}
//************************************

interface AA{
    void method1();
}
interface BB{
    
    void method2();
}

interface CC extends AA,BB{
    
}
接口实例

 

package com.atguigu.java1;
/*
 * 接口的应用:代理模式
 * 
 */
public class NetWorkTest {
    public static void main(String[] args) {
        Server server = new Server();
//        server.browse();
        ProxyServer proxyServer = new ProxyServer(server);
        
        proxyServer.browse();
        
    }
}

interface NetWork{
    
    public void browse();
    
}

//被代理类
class Server implements NetWork{

    @Override
    public void browse() {
        System.out.println("真实的服务器访问网络");
    }

}
//代理类
class ProxyServer implements NetWork{
    
    private NetWork work;
    
    public ProxyServer(NetWork work){
        this.work = work;
    }
    

    public void check(){
        System.out.println("联网之前的检查工作");
    }
    
    @Override
    public void browse() {
        check();
        
        work.browse();
        
    }
    
}
接口的应用:代理模式

 

package com.atguigu.java1;
/*
 * 接口的使用
 * 1.接口使用上也满足多态性
 * 2.接口,实际上就是定义了一种规范
 * 3.开发中,体会面向接口编程!
 * 
 */
public class USBTest {
    public static void main(String[] args) {
        
        Computer com = new Computer();
        //1.创建了接口的非匿名实现类的非匿名对象
        Flash flash = new Flash();
        com.transferData(flash);
        
        //2. 创建了接口的非匿名实现类的匿名对象
        com.transferData(new Printer());
        
        //3. 创建了接口的匿名实现类的非匿名对象
        USB phone = new USB(){

            @Override
            public void start() {
                System.out.println("手机开始工作");
            }

            @Override
            public void stop() {
                System.out.println("手机结束工作");
            }
            
        };
        com.transferData(phone);
        
        
        //4. 创建了接口的匿名实现类的匿名对象
        
        com.transferData(new USB(){
            @Override
            public void start() {
                System.out.println("mp3开始工作");
            }

            @Override
            public void stop() {
                System.out.println("mp3结束工作");
            }
        });
    }
}

class Computer{
    
    public void transferData(USB usb){//USB usb = new Flash();
        usb.start();
        
        System.out.println("具体传输数据的细节");
        
        usb.stop();
    }
    
    
}

interface USB{
    //常量:定义了长、宽、最大最小的传输速度等
    
    void start();
    
    void stop();
    
}

class Flash implements USB{

    @Override
    public void start() {
        System.out.println("U盘开启工作");
    }

    @Override
    public void stop() {
        System.out.println("U盘结束工作");
    }
    
}

class Printer implements USB{
    @Override
    public void start() {
        System.out.println("打印机开启工作");
    }

    @Override
    public void stop() {
        System.out.println("打印机结束工作");
    }
    
}
接口的匿名对象

 

interface A {
int x = 0;
}
class B {
int x = 1;
}
class C extends B implements A {
public void pX() {
System.out.println(x);//父类与接口都有x,无法进行区分

}
public static void main(String[] args) {
new C().pX();
} }
接口面试题

 

interface Playable {
void play();
}
interface Bounceable {
void play();
}

interface Rollable extends Playable, 
Bounceable {
Ball ball = new Ball("PingPang");//省略了public static final

class Ball implements Rollable {
private String name;
public String getName() 
{
public String getName() 
{
return name;
 }
public Ball(String name) {
this.name = name; 
}
public void play() {
ball = new Ball("Football");//ball是final修饰的,是常量,不可以new
System.out.println(ball.getName());
 }
}
接口面试题

 

 

 

    

 

内部类


 一、内部类的定义:在Java中,允许一个类A的定义位于另一个类B的内部,前者A称为内部类,后者B称为外部类。

 

二、内部类的分类:
   1.成员内部类(static成员内部类和非static成员内部类)
   2.局部内部类(不谈修饰符)、匿名内部类。
三、成员内部类作为类的角色:
   1.可以在内部定义属性、方法、构造器等结构
   2.可以声明为abstract类 ,因此可以被其它的内部类继承
   3.可以声明为final的,表示此类不能被继承。言外之意,不使用final,就可以被继承
   4.编译以后生成OuterClass$InnerClass.class字节码文件(也适用于局部内部类)

四、成员内部类作为类的成员的角色:

   1.可以被四种权限修饰;
   2.可以调用外部类的结构
   3. 可以被static修饰;
五、注意问题:
   1.如何实例化成员内部类的对象:
实例化静态的成员内部类  内部类:A  外部类:B
B.A  具体名 =  new B.A();

实例化非静态的成员内部类
B.A  具体名 = B.new A();

  2. 如何在成员内部类中区分调用外部类的结构

 3.开发中局部内部类的使用
public class InnerClassTest1 {
    
    
    //开发中很少见
    public void method(){
        //局部内部类
        class AA{
            
        }
    }
    
    
    //返回一个实现了Comparable接口的类的对象
    public Comparable getComparable(){
        
        //创建一个实现了Comparable接口的类:局部内部类
        //方式一:
//        class MyComparable implements Comparable{
//
//            @Override
//            public int compareTo(Object o) {
//                return 0;
//            }
//            
//        }
//        
//        return new MyComparable();
        
        //方式二:
        return new Comparable(){

            @Override
            public int compareTo(Object o) {
                return 0;
            }
            
        };
        
    }
    
}
开发中局部内部类的使用

 



 

      

 

posted @ 2021-10-08 10:25  莫尼莫尼  阅读(147)  评论(0编辑  收藏  举报