zoukankan      html  css  js  c++  java
  • 零基础学习java------day8------javabean编写规范,继承,static关键字,代码块,单例设计模式

    0. 今日内容提要

    1. javabean书写规范

    javabean:一个普通的类,用来描述事物的类,里面不包含任何的业务逻辑,只是用来存储数据。

      比如:Teacher,Student,Mobile....(作为数据的载体)

         vo,pojo,entity,model,dto。。。。

      规范:

        成员变量私有化

        提供get和set方法

        提供无参构造方法

        提供有参构造方法

    自动生成get和set方法:

      右键-->source-->generate  getters and  setters-->select All-->OK

    自动生成构造方法

      右键-->source-->generate constructor using fields-->selectALL/deSelectAll-->OK

    案例:

    编写javabean:
      商品编号
      商品名称
      商品价格
      商品数量

    public class Product {
        /**
         * 商品编号
         */
        private int proId;
        /**
         * 商品名称
         */
        private String proName;
        /**
         * 商品价格
         */
        private double proPrice;
        /**
         * 商品数量
         */
        private int proCount;
        public int getProId() {
            return proId;
        }
        public void setProId(int proId) {
            this.proId = proId;
        }
        public String getProName() {
            return proName;
        }
        public void setProName(String proName) {
            this.proName = proName;
        }
        public double getProPrice() {
            return proPrice;
        }
        public void setProPrice(double proPrice) {
            this.proPrice = proPrice;
        }
        public int getProCount() {
            return proCount;
        }
        public void setProCount(int proCount) {
            this.proCount = proCount;
        }
        public Product() {
            
        }
        public Product(int proId, String proName, double proPrice, int proCount) {
            super();
            this.proId = proId;
            this.proName = proName;
            this.proPrice = proPrice;
            this.proCount = proCount;
        }
        public static void main(String[] args) {
            Product d1 = new Product();
            d1.proId = 1;
            d1.proName="辣条";
            d1.proPrice = 3;
            d1.proCount = 100;
            Product d2 = new Product();
            d2.setProId(2);
            d2.setProName("火腿肠");
            d2.setProPrice(1);
            d2.setProCount(400);
            Product d3 = new Product(3,"老干妈",6.5,300);
        }
    }
    javabean

    2. 同名局部变量和成员变量的调用问题

    public class Person {
        String name = "张三";
        // 方法一
        public void print() {
            System.out.println(name);
        }
        // 方法二
        public void print(String name) {
            System.out.println(name);
        }
        // 方法三
        public void print1(String name) {
            System.out.println(this.name);
        }
        public static void main(String[] args) {
            Person p = new Person();
            System.out.println(p.name);//张三,因为成员变量有初始值,就是张三
            p.name = "李四";
            p.print();//李四,因为成员变量已经被改成了李四
            p.print("王五");// 王五,因为就近原则,默认使用局部变量
            p.print1("赵六");// 李四,使用this调用的还是成员变量,成员变量是李四    
        }
    }

    3. static 关键字

      静态的方法中只能调用外部用static修饰的变量和方法,如果非要调用非静态的,需要创建对象。原因是静态的变量或方法,最先加载到内存中,而成员变量或是成员方法只能在创建新对象后才会在堆中产生。如果此时没有对象,那么成员变量或成员方法还不存在,所以不能调用。

    静态变量和成员变量到底有什么区别?

      静态变量只有一个,其被所有对象共享,而成员变量则不一样,每个对象都会有自己的成员变量,如下图,黄色是静态变量,车把等就是成员变量对象o和对象o1都有自己的成员变量

    简述static关键字

       static可以用来修饰变量和方法,被static修饰的变量和方法就变成了静态变量和静态方法。随着类的加载而加载,先于对象的存在,被所有的对象所共享,可以使用类名词调用,也可以使用对象调用,推荐使用类名调用,静态的方法中只能调用外部用static修饰的变量和方法

     成员变量:对象名调用    对象名.成员变量  如 p.name;

     静态变量:类名调用        类名.静态变量    如  StaticDemo.b

     成员变量:也叫实例变量    实例-----对象

    静态变量:  也叫类变量

    案例

    public class StaticDemo {
        int b;//成员变量
        static int a;
        public static void main(String[] args) {
            // static int c=1;  注意局部变量不能用static来修饰
            System.out.println(a);
            System.out.println(b);//此处会报错,因为b是成员变量,而此打印操作是在静态方法中进行
        }
    }

    运行结果如下图

    如果非要在静态方法中调用非静态的事务,只能创建对象,如下

    public class StaticDemo {
        int b;//成员变量
        static int a;
        public static void main(String[] args) {
            System.out.println(a);
            StaticDemo sd = new StaticDemo();
            System.out.println(sd.b);
        }
    }

    4. 代码块

     (1)静态代码块:

      static{ }  随着类的加载而执行一次

    public class CodeBlockDemo {
        static {
            System.out.println("我是静态代码块");
        }
        public static void main(String[] args) {        
        }
    }
    // 运行结果: 我是静态代码块

    原因:main方法一启动,类就要加载,类一加载,静态代码块就会执行

    (2)构造代码块

    { }   每创建一个对象就会执行一次

    注意静态代码块先于构造代码块,先于构造方法执行

    (3)局部代码块:

    定义在方法中的{ }   局部代码块执行完毕后会立马释放,局部代码块很少使用,但当方法中有一部分代码很耗内存,当其执行完不释放掉的话,后面代码运行效率很低,这时就可以用局部代码块来写这些代码

    public class CodeBlockDemo {
        static {
            System.out.println("我是静态代码块");
        }
        {
            System.out.println("我是构造代码块");
        }
        public CodeBlockDemo() {
            System.out.println("我是无参构造方法");
        }
        public CodeBlockDemo(String a) {
            System.out.println("我是有参构造方法");
        }
        public static void main(String[] args) {
            CodeBlockDemo c1 = new CodeBlockDemo();//当没创建此对象时,运行的结果只有 “我是代码块”,说明构造方法和构造代码块只能是创建了对象才会产生
        }
    }
    运行结果: 我是代码块 我是构造方法 我是无参构造方法

    由下面的代码可看出静态代码块先于构造代码块,先于构造方法执行

    public class CodeBlockDemo {
        public CodeBlockDemo() {
            System.out.println("我是无参构造方法");
        }
        public CodeBlockDemo(String a) {
            System.out.println("我是有参构造方法");
        }
        {
            System.out.println("我是构造代码块");
        }
        static {
            System.out.println("我是静态代码块");
        }
        public static void main(String[] args) {
            CodeBlockDemo c = new CodeBlockDemo();
            CodeBlockDemo c1 = new CodeBlockDemo("a");
        }
    }

    运行结果(并没按照代码顺序进行打印)

     练习

    统计一个类中创建对象的个数

    此处利用构造代码块来做,构造方法也行,但没构造代码块合适,因为无论是有参对象还是无参对象构造代码块都会执行

    public class CountObject {
        static int count = 0;
        {
            count ++;
        }
        public static void main(String[] args) {
        CountObject c1 = new CountObject();
        CountObject c2 = new CountObject();
        CountObject c3 = new CountObject();
        // CountObject c4 = new CountObject();
        System.out.println("创建对象的个数为"+ count);//3
        }
    }

    5. 继承

     (1)格式:

     class 子类名  extends  父类名{ }

    被继承的类叫做父类,基类或超类;继承的类叫子类或派生类

    (2)注意事项

    java中的继承只支持单继承,不支持多继承(即一个子类只能有一个父类),但其支持多层继承

    object:(万类之祖)如果一个类没有继承任何类,那么它默认继承自Object

    父类中的私有变量或方法不能被继承

    案例

     1 public class ExtendsDemo {
     2     public static void main(String[] args) {
     3         Student s = new Student();
     4         System.out.println(s.age);
     5         System.out.println(s.height); //此行代码可正常运行,表示java中的继承可以多层继承
     6         s.eat();
     7         
     8     }
     9 }
    10 class SuperPerson  {
    11     double height;
    12 }
    13 class Person extends SuperPerson{
    14     String name;
    15     int age;
    16     char gender;
    17     public void eat() {
    18         System.out.println("吃嘛嘛香");
    19     }
    20 }
    21 class Student extends Person{
    22     double score;

    (3)同一个文件中定义多个类

       一个文件中可以定义多个类,但必须只能有一个类使用public类,并且要用public修饰的类必须和文件名相同,此外main方法也必须定义在用public修饰的类中(定义在非public修饰的类中无法执行)

      同一个包中不能定义名字相同的类

     练习

    定义一个Dog

      包含name  gender   furColor   lookDoor()

    定义Dog的子类ChinaDog:

      眼睛的颜色eyeColor

    定义Dog的子类:UsaDog

      weight; age

    创建一个ChinaDog对象,并赋值;创建一个UsaDog,并赋值

     1 public class DogTest {
     2     public static void main(String[] args) {
     3         ChinaDog cd1 = new ChinaDog();
     4         cd1.eyescolor = "黑色";
     5         cd1.furColor = "黄色";
     6         cd1.gender = '公';
     7         cd1.name = "小黄";
     8         System.out.println(cd1.name+cd1.gender+cd1.furColor+cd1.eyescolor);
     9     }
    10 }
    11 
    12 class Dog {
    13     String name;
    14     char gender;
    15     String furColor;
    16     public void lookDoor() {
    17         System.out.println("看门");
    18     }
    19 }
    20 class ChinaDog extends Dog{
    21     String eyescolor;
    22 }
    23 
    24 class UsaDog extends Dog{
    25     double weight;
    26     int age;
    27 }
    View Code

    5.4 继承中成员变量的关系

      当调用某子类变量时,先在子类中找,再去父类中找,父类中没有就报错

    5.5 super关键字

    super:可以看做是父类中的一个引用(指代父类中的对象),用与区分子类中和父类中同名的成员(成员变量,成员方法),super指代的是父类中的值,只能在之类中使用

    this:可以看做是本类中的一个对象,用于区分同名的局部变量和成员变量,this指代的是成员变量,只能在本类中使用

    this和super后面可以跟成员变量和成员方法(不能是局部变量)

      this.成员变量       this.成员方法()

      super.成员变量    this.成员方法()

    调用构造方法:

      this(参数):调用本类中的构造方法

      super(): 调用父类中的构造方法

    this和super不能用于static方法中

    原因:静态方法先于对象产生,而this和super指代对象,在静态方法中,对象都还没产生,所以this和static不能用于static方法中

    5.6  继承中构造方法的关系

    子类中的构造方法会默认调用父类中无参数的构造方法,如果父类中没有无参数的构造方法,子类必须直接或简介的调用父类中的构造方法

    如下代码子类会默认调用父类构造方法

     1 //创建测试类
     2 public class ExtendsConstrutorDemo {
     3     public static void main(String[] args) {
     4         SonClass s1 = new SonClass();
     5     }
     6 }
     7 // 创建一个父类
     8 class FatherClass {
     9     public FatherClass() {
    10         System.out.println("我是父类无参构造方法");
    11     }
    12 }
    13 // 创建子类
    14 class SonClass extends FatherClass{
    15     public SonClass() {
    16      // 此处默认会有super(),用来调用父类构造方法,只能放第一行
    17 System.out.println("我是子类无参构造方法"); 18 } 19 }

    打印结果为

    若第9行的代码中,父类构造方法加参数,变成如下

    public FatherClass(String str){

    这样的话,子类中调用父类构造方法处就会报错(提示无父类构造方法,即super()调用不到父类中的构造方法)

     

    解决办法:

    第一种:直接调用:

    在super()中加一个参数即可,如super(“str”)

     第二种:间接调用

    在本类中再写一个有参的构造方法,利用this调用这个有参的构造方法,部分代码如下图

    调用本类中的构造方法:

    this(参数值);此也一定要放到第一行,和super()一样

     为什么要调用父类的构造方法?

      子类要继承父类中的数据,父类中有时候会有些成员变量和成员方法,而要调用父类中的数据,父类就要将这些数据初始化(即将这些数据创建好),而调用父类造方法,就能达到父类数据初始化的效果。

     练习

    /**
    * 构建一个父类,两个子类
    * 1.构造两个父类中和子类中名字一样的属性和方法,属性赋不同的值
    * 分别用父类和子类的对象调用
    * 2.为父类和子类提供无参构造方法,并显示调用super();
    * 3.为子类提供有参构造方法1,并显示调用本类中的无参构造方法this();
    * 4.为子类提供有参构造方法2,并显示调用父类中的构造方法
    * 5.为父类提供有参数构造方法,在子类中构造方法中调用
    */
    package com._51doit.javase.day08;
    
    public class ExtendsTest1 {
        public static void main(String[] args) {
            FuClass f1 = new FuClass();
            System.out.println(f1.name);//
            NvClass n1 = new NvClass(4);
            n1.sleep();
        }
    }
    
    class FuClass{
        String name = "老张";
        public FuClass() {
            super();//调用Object中的构造方法
        }
        public void sleep() {
            System.out.println("生前何须久睡死后自会长眠");
        }
            public FuClass(int a) {
            }
    }
    
    class ZiClass extends FuClass{
        public ZiClass() {
            super();
        }
        public ZiClass(int a) {//有参
            this();//调用本类中无参构造方法
        }
        String name = "大张";
        public void sleep() {
            System.out.println("中午不睡下午崩溃");
        }
    }
    class NvClass extends FuClass{
        String name = "小张";
        public NvClass(int b) {
            super(1);//调用父类中有参的构造方法
        }
        /*public void sleep() {
        System.out.println("别睡太晚,梦会太短");
        }*/
    }
    View Code

     5.7 继承中成员方法的关系

     与成员变量相似,先在子类中找,再去父类中找,父类中没有就报错

    5.8  方法的重载和方法的重写

     概念:

      重写(override):子类中出现了和父类中方法名一样,返回值类型,参数列表一样的方法,就叫做方法的重写

         重载(overload):一个类中可以存在多个名字相同的方法,但是必须保证参数的个数或类型不同,与返回值无关

       注解:@override   可以使用该注解验证重写格式是否正确,把它写到子类的方法上

     如:

    方法重写的注意事项

       1. 父类中的私有方法不能被重写(子类中可以有同名的方法,只是此种情况不叫方法的重写)

       2.  子类重写父类中的方法,访问权限不能更低(权限一次减小:public  default  protected  private)

       3.   静态的方法不能重写

     练习题

    按要求编写一个Java 应用程序:
    (1)编写一个矩形类Rect,包含:
    矩形的宽width;矩形的高height。
    两个构造方法:
    1.一个带有两个参数的构造方法,用于将width 和height 属性初化;
    2.一个不带参数的构造方法,将矩形初始化为宽和高都为10。
    两个方法:
    求矩形面积的方法area()
    求矩形周长的方法perimeter()
    (2)通过继承Rect 类编写一个具有确定位置的矩形类PlainRect,其确定位置用
    矩形的左上角坐标来标识,包含:
    添加两个属性:矩形左上角坐标startX 和startY。
    两个构造方法:
    带4 个参数的构造方法,用于对startX、startY、width 和height 属性
    初始化;
    不带参数的构造方法,将矩形初始化为左上角坐标、长和宽都为0
    的矩形;
    添加一个方法:
    判断某个点是否在矩形内部的方法isInside(double x,double y)。如在矩
    形内,返回true, 否则,返回false。
    提示:点在矩形类是指满足条件:
    x>=startX&&x<=(startX+width)&&y<=startY&&y>=(startY-height)
    (3)编写PlainRect 类的测试程序
    创建一个左上角坐标为(10,10),长为20,宽为10 的矩形对象;
    计算并打印输出矩形的面积和周长;
    判断点(25.5,13)是否在矩形内,并打印输出相关信息。

     6. final

     final 可以用来修饰类,方法,变量

    final 修饰的类不能被继承

    final 修饰的方法不能被重写

    final 修饰的变量值不能改变,final修饰的变量要有初始值

    一般我们创建常量:public static  final

           final: 限制值不能变

           static: 只有一份

    两种文法

    final static
    final finally finalize

    7. 单例设计模式

     概述:一个类只产生一个实例对象

    分类:饱汉式

       懒汉式

    实现步骤:

      1. 私有构造方法

      2. 创建最终静态对象

      3. 提供公共的访问对象

    如何实现一个类只能创建一个对象?

    正常情况创建对象的形式为:类名   对象名  =   new   类的构造方法

    思路:将构造方法属性变为私有,即用private修饰,这样外部类就不能通过  new  类构造方法来创建对象了。但自己可以在类的内部创建一个公有的对象(即为成员变量,加上static就变成静态变量,此处因为是各个类公有,所以为应该为静态变量),供外部类调用。

    如下:

     1 public class Singleton {
     2     public static void main(String[] args) {
     3         Singleton1 s1 = Singleton1.s;// 通过类调用静态变量s得到一个对象
     4         Singleton1 s2 = Singleton1.s;
     5         System.out.println(s1 == s2);
     6     }    
     7 }
     8 
     9 
    10 class Singleton1 {
    11     public static Singleton1 s = new Singleton1();//此处一定要加static,让Singleton1类型的s成员变量变成静态变量,不然只能通过对象调用,不能类调用。
    12     private Singleton1() {        
    13     }
    14 }

    运行结果为true,说明对象s1和对象s2是同一个对象

    但这种直接获取成员变量的形式不好,应该通过创建方法的形式,如下(也称饱汉式

    public class Singleton {
        public static void main(String[] args) {
            Singleton1 s1 = Singleton1.getInstance();
            Singleton1 s2 = Singleton1.getInstance();
            System.out.println(s1 == s2);
        }    
    }
    
    class Singleton1 {
        public static Singleton1 s = new Singleton1();
       // 创建一个静态的访问方法,返回本类中唯一的对象
    public static Singleton1 getInstance() { //此处的Singleton1表示返回Singleton1类型的值 return s; } private Singleton1() { } }
    运行结果 true

    懒汉式

    由于懒汉式一开始就创立了一个对象,即在堆中占据了一个内存空间,若其他类一直没有去调用这个获取对象的方法,这样就很浪费资源,所以就有懒汉式的出现

    public class Singleton2 {
        public static void main(String[] args) {
            Singleton3 s1 = Singleton3.getInstance();
            Singleton3 s2 = Singleton3.getInstance();
            System.out.println(s1);
        }
    }
    class Singleton3{
        public static Singleton3 s;
        public static Singleton3 getInstance() {
            if(s==null) {
                s = new Singleton3();
            }
            return s;
        }
        
        private Singleton3() {
            
        }
    }

    懒汉式也存在问题,会有线程安全问题(创建多个对象),如:

     当一个线程Thread1刚执行完if判断语句时,cpu切换至另一个线程,此线程一直执行完,创建了一个s对象,此时cpu又切换回去执行线程Thread1,此时就又会创建一个s对象,这样就会创建多个对象(如果有多个线程)

     解决方法,上一把锁,使用同步方法解决(即在方法的修饰符位置加上synchronized),如下:

    public synchronized static Singleton3 getInstance()

    -

  • 相关阅读:
    NSDate
    Info.plist字段列表详解
    面向对象编程思想以及强、弱引用总结
    分类(类别/Category)与 类扩展(Extension)
    UIAlertView
    SQLite3的运用
    快速创建单例
    C++ 常用设计模式
    I2S 总线学习:2-I2S驱动WM8978
    设计模式的七大原则
  • 原文地址:https://www.cnblogs.com/jj1106/p/11329133.html
Copyright © 2011-2022 走看看