零基础学习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()

 

 

-

 

posted @ 2019-08-09 19:52  一y样  阅读(277)  评论(0编辑  收藏  举报