zoukankan      html  css  js  c++  java
  • Java面向对象《三》

    一、关键字static

    1、使用范围:在Java类中,可用static修饰属性、方法、代码块、内部类

    2、被修饰的成员特点:

    1)随着类的加载而加载

    2)优先于对象存在

    3)修饰的成员,被所有对象所共享

    4)访问权限允许时,可不创建对象,直接被类调用

    类变量内存解析(下图中的String字符串应该存放在方法区中,我们为了简化就把String字符串放在了堆中):

    3、类方法

    注意:

    1)没有对象的实例时,可以用类名.方法名()的形式访问由static修饰的类方法。

    2)在static方法内部只能访问类的static修饰的属性或方法,不能访问类的非static的结构。

    3)因为不需要实例就可以访问static方法,因此static方法内部不能有this。(也 不能有super ? YES!)

    4)static修饰的方法不能被重写

    二、单例设计模式

    所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对 某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。 如果我们要让类在一个虚拟机中只能产生一个对象,我们首先必须将类的构 造器的访问权限设置为private,这样,就不能用new操作符在类的外部产生 类的对象了,但在类内部仍可以产生该类的对象。因为在类的外部开始还无 法得到类的对象,只能调用该类的某个静态方法以返回类内部创建的对象, 静态方法只能访问类中的静态成员变量,所以,指向类内部产生的该类对象 的变量也必须定义成静态的。

    1、单例(Singleton)设计模式-饿汉式

    class Singleton {
    // 1.私有化构造器
    private Singleton() {
    }
    // 2.内部提供一个当前类的实例
    // 4.此实例也必须静态化
    private static Singleton single = new Singleton();
    // 3.提供公共的静态的方法,返回当前类的对象
    public static Singleton getInstance() {
    return single;
    }
    }

    2、单例(Singleton)设计模式-懒汉式(懒汉式暂时还存在线 程安全问题,讲到多 线程时,可修复)

    class Singleton {
    // 1.私有化构造器
    private Singleton() {
    }
    // 2.内部提供一个当前类的实例
    // 4.此实例也必须静态化
    private static Singleton single;
    // 3.提供公共的静态的方法,返回当前类的对象
    public static Singleton getInstance() {
    if(single == null) {
    single = new Singleton();
    }
    return single;
    }
    }

    单例设计模式优点:由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的 产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可 以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方 式来解决。

    三、main()方法语法

    1、由于Java虚拟机需要调用类的main()方法,所以该方法的访问权限必须是 public,又因为Java虚拟机在执行main()方法时不必创建对象,所以该方法必须 是static的,该方法接收一个String类型的数组参数,该数组中保存执行Java命令 时传递给所运行的类的参数。

    2、又因为main() 方法是静态的,我们不能直接访问该类中的非静态成员,必须创 建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员,这种情 况,我们在之前的例子中多次碰到。

    五、代码块

    1、作用:对Java类或对象进行初始化

    2、分类:一个类中代码块若有修饰符,则只能被static修饰,称为静态代码块 (static block),没有使用static修饰的,为非静态代码块。

    3、static代码块通常用于初始化static的属性

    4、静态代码块:用static 修饰的代码块

    1). 可以有输出语句。

    2). 可以对类的属性、类的声明进行初始化操作。

    3). 不可以对非静态的属性初始化。即:不可以调用非静态的属性和方法。

    4). 若有多个静态的代码块,那么按照从上到下的顺序依次执行。

    5). 静态代码块的执行要先于非静态代码块。

    6). 静态代码块随着类的加载而加载,且只执行一次。

    5、非静态代码块:没有static修饰的代码块

    1). 可以有输出语句。

    2). 可以对类的属性、类的声明进行初始化操作。

    3). 除了调用非静态的结构外,还可以调用静态的变量或方法。

    4). 若有多个非静态的代码块,那么按照从上到下的顺序依次执行。

    5). 每次创建对象的时候,都会执行一次。且先于构造器执行。

    6、程序中成员变量赋值的顺序

    声明成员变量的默认初始化--------->显式初始化、多个初始化块依次被执行(同级别下按先后顺序执行)---------->构造器再对成员进行初始化操作------------>通过”对象.属性”或”对象.方法”的方式,可多次给属性赋值

    四、final关键字

    在Java中声明类、变量和方法时,可使用关键字final来修饰,表示“最终的”。

    1)final标记的类不能被继承。提高安全性,提高程序的可读性。

    2)final标记的方法不能被子类重写。

    3)final标记的变量(成员变量或局部变量)即称为常量。名称大写,且只 能被赋值一次。

    final标记的成员变量必须在声明时或在每个构造器中或代码块中显式赋 值,然后才能使用。

    4)static final:全局常量

    7、抽象类与抽象方法

    1、用abstract关键字来修饰一个类,这个类叫做抽象类。

    2、用abstract来修饰一个方法,该方法叫做抽象方法。

    抽象方法:只有方法的声明,没有方法的实现。以分号结束: 比如:public abstract void talk();

    3、含有抽象方法的类必须被声明为抽象类。

    4、抽象类不能被实例化。抽象类是用来被继承的,抽象类的子类必须重 写父类的抽象方法,并提供方法体。若没有重写全部的抽象方法,仍 为抽象类。

    5、不能用abstract修饰变量、代码块、构造器

    6、不能用abstract修饰私有方法、静态方法、final的方法、final的类。

    abstract class ppeople{
        ppeople(){
            System.out.println("people is constructing");
        }
        public int age;
    }
    class sstudent extends ppeople{
        sstudent(){
            System.out.println("student is constructing");
        }
    }
    public class test1 {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            sstudent p = new sstudent();
        }
    }
    /*输出
     * people is constructing
     * student is constructing
     * */

    7、抽象类的匿名子类对象

    abstract class ppeople{
        public abstract void test1();
        public abstract void test2();
    }
    public class test1 {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            //创建了一个匿名子类的对象
            ppeople p = new ppeople() {
    
                @Override
                public void test1() {
                    // TODO Auto-generated method stub
                    System.out.println("11111");
                }
                @Override
                public void test2() {
                    // TODO Auto-generated method stub
                    System.out.println("222222");
                }
            };
            //相当于多态
            p.test1();
            p.test2();
        }
    }
    /*输出
     * 11111
     * 222222
     * */

    五、模板方法设计模式

    抽象类体现的就是一种模板模式的设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展、改造,但子类总体上会保留抽象类的行为方式。

    解决的问题:

    1)当功能内部一部分实现是确定的,一部分实现是不确定的。这时可以 把不确定的部分暴露出去,让子类去实现。

    2)换句话说,在软件开发中实现一个算法时,整体步骤很固定、通用, 这些步骤已经在父类中写好了。但是某些部分易变,易变部分可以抽 象出来,供不同子类实现。这就是一种模板模式。

    六、接口(Interface)

    1、接口(interface)是抽象方法和常量值定义的集合。

    2、接口的特点

    1)用interface来定义。

    2)接口中的所有成员变量都默认是由public static final修饰的。

    3)接口中的所有抽象方法都默认是由public abstract修饰的。

    4)接口中没有构造器。

    5)接口采用多继承机制。

    3、定义Java类的语法格式:先写extends,后写implements(class SubClass extends SuperClass implements InterfaceA{ })

    4、一个类可以实现多个接口,接口也可以继承其它接口。

    5、实现接口的类中必须提供接口中所有方法的具体实现内容,方可实 例化。否则,仍为抽象类。

    6、接口的主要用途就是被实现类实现。(面向接口编程)

    7、与继承关系类似,接口与实现类之间存在多态性

    8、接口和类是并列关系,或者可以理解为一种特殊的类。从本质上讲, 接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义 (JDK7.0及之前),而没有变量和方法的实现。

    //一个类可以实现多个无关的接口
    interface Runner { public void run();}
    interface Swimmer {public double swim();}
    class Creator{public int eat(){…}} 
    class Man extends Creator implements Runner ,Swimmer{
    public void run() {……}
    public double swim() {……}
    public int eat() {……}
    }
    //与继承关系类似,接口与实现类之间存在多态性
    public class Test{
    public static void main(String args[]){
    Test t = new Test();
    Man m = new Man();
    t.m1(m);
    t.m2(m);
    t.m3(m);
    }
    public String m1(Runner f) { f.run(); }
    public void m2(Swimmer s) {s.swim();}
    public void m3(Creator a) {a.eat();}
    }
    interface MyInterface{
    String s=“MyInterface”;
    public void absM1();
    }
    interface SubInterface extends MyInterface{
    public void absM2();
    }
    public class SubAdapter implements SubInterface{
    public void absM1(){System.out.println(“absM1”);}
    public void absM2(){System.out.println(“absM2”);}
    }
    实现类SubAdapter必须给出接口SubInterface以及父接口MyInterface中
    所有方法的实现。否则,SubAdapter仍需声明为abstract的。
    //接口实现多态
    interface ppeople{
        public abstract void test1();
        public abstract void test2();
    }
    class sstudent implements ppeople{
        @Override
        public void test1() {
            // TODO Auto-generated method stub
            System.out.println("11111");
        }
        @Override
        public void test2() {
            // TODO Auto-generated method stub
            System.out.println("22222");
        }
    }
    public class test1 {
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            ppeople p = new sstudent();
            //相当于多态
            p.test1();
            p.test2();
        }
    }
    /*输出
     * 11111
     * 222222
     * */

    9、接口的应用:代理模式

    代理模式是Java开发中使用较多的一种设计模式。代理设计就是为其他对象提供一种代理以控制对这个对象的访问

    示例:

    interface Network {
    public void browse();
    }
    // 被代理类
    class RealServer implements Network {
    @Override
    public void browse() {
    System.out.println("真实服务器上
    网浏览信息");
    }
    }
    // 代理类
    class ProxyServer implements Network {
    private Network network;
    public ProxyServer(Network network) {
    this.network = network;
    }
    public void check() {
    System.out.println("检查网络连接等操作");
    }
    public void browse() {
    check();
    network.browse();
    }
    }
    public class ProxyDemo {
    public static void main(String[] args) {
    Network net = new ProxyServer(new
    RealServer());
    net.browse();
    }
    }

    10、接口和抽象类之间的对比

    interface A {
    int x = 0;
    }
    class B {
    int x = 1;
    }
    class C extends B implements A {
    public void pX() {
    System.out.println(x);  出错
    /*
    这个x会报错,因为编译器不知道这个x时接口的x还是B类的x
    如果B继承A,C继承B,且A、B、C都有自己的一个变量x,那么就会根据就近原则调用x
    
    */
    System.out.println(super.x); 调用B类的
    System.out.println(A.x);   调用A类的
    }
    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");
    }
    class Ball implements Rollable {
    private String name;
    public String getName() {
    return name;
    }
    public Ball(String name) {
    this.name = name;
    }
    public void play() { //两个接口中都有play方法,这样写的话这个方法算作两个,不会报错
    //ball是接口中定义的变量,接口中变量默认是final类型,不可以改变
    ball = new Ball("Football"); //错误
    System.out.println(ball.getName());
    }
    }

    11、Java8关于接口的改进

    Java 8中,你可以为接口添加静态方法和默认方法。从技术角度来说,这是完 全合法的,只是它看起来违反了接口作为一个抽象定义的理念。

    静态方法:使用 static 关键字修饰。可以通过接口直接调用静态方法,并执行 其方法体。我们经常在相互一起使用的类中使用静态方法。你可以在标准库中 找到像Collection/Collections或者Path/Paths这样成对的接口和类。

    默认方法:默认方法使用 default 关键字修饰。可以通过实现类对象来调用。 我们在已有的接口中提供新方法的同时,还保持了与旧版本代码的兼容性。 比如:java 8 API中对Collection、List、Comparator等接口提供了丰富的默认 方法。

    注意:

    1)若一个接口中定义了一个默认方法,而另外一个接口中也定义了一个同名同 参数的方法(不管此方法是否是默认方法),在实现类同时实现了这两个接 口时,会出现:接口冲突。

    解决办法:实现类必须覆盖接口中同名同参数的方法,来解决冲突。

    2)若一个接口中定义了一个默认方法,而父类中也定义了一个同名同参数的非 抽象方法,则不会出现冲突问题。因为此时遵守:类优先原则。接口中具有 相同名称和参数的默认方法会被忽略。

    七、内部类

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

    1)和外部类不同,Inner class还可以声明为private或protected;

    2)可以调用外部类的结构

    3)Inner class 可以声明为static的,但此时就不能再使用外层类的非static的成员 变量;

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

    1)可以在内部定义属性、方法、构造器等结构

    2)可以声明为abstract类 ,因此可以被其它的内部类继承

    3)可以声明为final

    4)编译以后生成OuterClass$InnerClass.class字节码文件(也适用于局部内部类

    【注意】

    1). 非static的成员内部类中的成员不能声明为static的,只有在外部类或static的成员 内部类中才可声明static成员。

    2). 外部类访问成员内部类的成员,需要“内部类.成员”或“内部类对象.成员”的方式

    3). 成员内部类可以直接使用外部类的所有成员,包括私有的数据

    4). 当想要在外部类的静态成员部分使用内部类时,可以考虑内部类声明为静态的 

    示例:

    class Outer {
    private int s;
    public class Inner {
    public void mb() {
    s = 100;
    System.out.println("在内部类Inner中s=" + s);
    }
    }
    public void ma() {
    Inner i = new Inner();
    i.mb();
    }
    }
    public class InnerTest {
    public static void main(String args[]) {
    Outer o = new Outer();
    o.ma();
    }
    }
    public 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 static void main(String args[]) {
    Outer a = new Outer();
    Outer.Inner b = a.new Inner();
    b.mb(333);
    }
    }

    3、如何声明局部内部类

    4、如何使用局部内部类

    1)只能在声明它的方法或代码块中使用,而且是先声明后使用。除此之外的任何地方 都不能使用该类

    2)但是它的对象可以通过外部方法的返回值返回使用,返回值类型只能是局部内部类 的父类或父接口类型 

    5、局部内部类的特点

    1)内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但 是前面冠以外部类的类名和$符号,以及数字编号。

    2)只能在声明它的方法或代码块中使用,而且是先声明后使用。除此之外的任何地方 都不能使用该类。

    3)局部内部类可以使用外部类的成员,包括私有的。

    4)局部内部类可以使用外部方法的局部变量,但是必须是final的。由局部内部类和局 部变量的声明周期不同所致。

    5)局部内部类和局部变量地位类似,不能使用public,protected,缺省,private

    6)局部内部类不能使用static修饰,因此也不能包含静态成员

    6、匿名内部类

    1)匿名内部类不能定义任何静态成员、方法和类,只能创建匿名内部类的一 个实例。一个匿名内部类一定是在new的后面,用其隐含实现一个接口或 实现一个类。

    2)格式: new 父类构造器(实参列表)|实现接口(){ //匿名内部类的类体部分 }

    3)匿名内部类的特点:  匿名内部类必须继承父类或实现接口  匿名内部类只能有一个对象  匿名内部类对象只能使用多态形式引用

    示例:

    interface A{
    public abstract void fun1();
    }
    public class Outer{
    public static void main(String[] args) {
    new Outer().callInner(new A(){
    //接口是不能new但此处比较特殊是子类对象实现接口,只不过没有为对象取名
    public void fun1() {
    System.out.println(“implement for fun1");
    }
    });// 两步写成一步了
    }
    public void callInner(A a) {
    a.fun1();
    }
    }

     

    编译以后生成OuterClass$InnerClass.class字节码文件(也适用于局部内部类)

  • 相关阅读:
    【SSH】——Hibernate三种状态之间的转化
    【工具学习】——教你读懂Maven的配置文件
    【SSH】——封装参数不确定的分页查询
    从零开始配置Jenkins(二)——常见问题及排错思路
    从零开始配置Jenkins(一)——基本配置
    Chrome插件集合
    Vue.js——vue-resource全攻略
    vue中用qs传参发送axios请求
    vue项目打包后首页一片空白解决办法和具体原因总结
    vue开发环境和生产环境里面解决跨域的几种方法
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/14727608.html
Copyright © 2011-2022 走看看