Java基础

JAVA面向对象

2018-09-11  本文已影响0人  磊_5d71

一、类与对象的关系

package com.alan.animal;
/**
 * 宠物猫类
 * @author alan
 *
 */
public class Cat {

    //属性:昵称、年龄、体重、品种
    
    String name; //昵称 String 默认值null
    int month;   //年龄  int 默认值为 0
    double weight;  //体重 double 默认值为0.0
    String species; //品种
    
    
    //方法:跑动、吃东西
    //跑动的方法
    public void run() {
        System.out.println("小猫快跑");
    }
    //对跑动的方法进行重载
    public void run(String name) {
        System.out.println(name+"快跑");
    }
    //吃东西的方法
    public void eat() {
        System.out.println("小猫吃鱼");     
    }

}

package com.alan.animal;

public class CatTest {

    public static void main(String[] args) {

        //对象实例化
        Cat one = new Cat();
        
        //测试 调用方法
        one.eat();
        one.run();
        one.name = "花花";
        //在类没有初始化的情况下,构造函数对其进行默认的赋值 String 为null ,int 为0,double为0.0
        System.out.println("name="+one.name);
        System.out.println("species="+one.species);
        System.out.println("month="+one.month);
        System.out.println("weight="+one.weight);
        one.run(one.name);
        
    }

}

单一责任原则

实例化对象

分为两个部分:

构造方法(构造函数)

在new的时候构造方法会被调用,不能被对象单独调用
1、构造方法与类同名且没有返回值。
2、只能在对象实例化的时候调用。
3、当没有指定构造方法时,系统会自动添加无参的构造方法。
4、就近原则,如果使用name=name赋值,会优先选择同一个作用域,进行赋值,所以要使用不同名字,或者用this.name=name 进行赋值。


this关键字

this与创建的对象具有相同的ID值,说明this调用的就是当前的对象
this();可以调用无参构造方法,但是一定是在其他构造方法的第一行。
其他的方法不能调用构造函数。

二、Java封装

将类的某些信息隐藏在类内部,不允许外部程序直接访问。


image.png

创建包

同一个包中不允许出现相同文件名的Cat,引用同名的

package com.alan.test;

import com.alan.animal.Cat; 
import com.alan.mechanics.*; //通过.*直接加载到直接的类,不能使用com.alan.*这种方式

public class Test {

    public static void main(String[] args) {
        
        com.alan.mechanics.Cat one = new com.alan.mechanics.Cat(); //直接导入的是animal中的Cat,如果需要用mechanics中的需要在代码中加入com等具体的包路径
//      System.out.println("调用成功!");
    }

}

static关键字

//static 静态 静态成员 类成员 ,所有对象都使用一块内存空间,所以所有的实例化对象,static修饰的值都相同
public static int price; //用static修饰后 price变为斜体

1、类对象共享该内存信息
2、类加载时产生,直到类销毁的时候释放。生命周期长。
3、静态成员的访问方式,既可以通过对象名访问,也可以通过类名访问。
one.price (对象名访问) Cat.price(类名访问)
4、当static修饰方法时,该方法为静态方法,推荐采用类名调用,如Cat.eat();
5、有静态的属性和方法,静态方法中不能直接访问同一个类的非静态成员,只能直接调用同一个类中的静态成员。只能通过实例化后进行访问没有静态的类,没有静态的局部变量。

代码块{}


command+shift+f 行内容过长,换行快捷键。

三、Java封装综合案例

package com.alan.model;

/**
 * 学生类
 * 
 * @author alan
 *
 */
public class Student {

    // 成员属性:学号、姓名、性别、年龄、专业对象
    private String studentNo;
    private String studentName;
    private String studentSex;
    private int studentAge;
    private Subject studentSubject;

    // 无参构造
    public Student() {

    }

    // 带参构造
    public Student(String studentNo, String studentName, String studentSex, int studentAge,Subject studentSubject) {

        this.setStudentNo(studentNo);
        this.setStudentName(studentName);
        this.setStudentSex(studentSex);
        this.setStudentAge(studentAge);
        this.setStudentSubject(studentSubject);
    }

    /**
     * 获取专业对象,如果没有实例化,先实例化后再返回
     * @return 专业对象
     */
    public Subject getStudentSubject() {
        if(this.studentSubject == null)
            this.studentSubject = new Subject(); //无参构造的重要性就提现出来了
        return studentSubject;
    }

    public void setStudentSubject(Subject studentSubject) {
        
        this.studentSubject = studentSubject;
    }

    public String getStudentNo() {
        return studentNo;
    }

    public void setStudentNo(String studentNo) {
        this.studentNo = studentNo;
    }

    public String getStudentName() {
        return studentName;
    }

    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }

    public String getStudentSex() {
        return studentSex;
    }

    public void setStudentSex(String studentSex) {
        this.studentSex = studentSex;
    }

    public int getStudentAge() {
        return studentAge;
    }

    /**
     * 给年龄赋值。限定大于10,小于50,否则赋值为18
     * 
     * @param studentAge 传入的年龄
     */
    public void setStudentAge(int studentAge) {
        if (studentAge < 10 || studentAge > 50)
            this.setStudentAge(18);
        else
            this.studentAge = studentAge;
    }

    /**
     * 学生自我介绍的方法
     * 
     * @return 自我介绍信息,包括姓名、学号、性别、年龄
     *
     */
    public String introduction() {

        String str = "学生信息如下:\n姓名:" + this.getStudentName() + "\n学号:" + this.getStudentNo() + "\n性别:"
                + this.getStudentSex() + "\n年龄:" + this.getStudentAge()+ "\n所报专业名称:" + this.getStudentSubject().getSubjectName() + "\n学制年限:"
                        + this.getStudentSubject().getSubjectLife();
        return str;

    }

    /**
     * 学生自我介绍的方法
     * 
     * @param subjectName 所学专业名称
     * @param subjectLife 学制年限
     * @return 自我介绍信息,包括姓名、学号、性别、年龄、所学专业名称、学制年限
     */

    public String introduction(String subjectName, int subjectLife) {
        String str = "学生信息如下:\n姓名:" + this.getStudentName() + "\n学号:" + this.getStudentNo() + "\n性别:"
                + this.getStudentSex() + "\n年龄:" + this.getStudentAge() + "\n所报专业名称:" + subjectName + "\n学制年限:"
                + subjectLife;
        return str;
    }
    
    /**
     * 学生自我介绍的方法
     * @param sub1 传入学科对象
     * @return 自我介绍信息,包括姓名、学号、性别、年龄、所学专业名称、学制年限
     */
    public String introduction(Subject sub1) {

        String str = "学生信息如下:\n姓名:" + this.getStudentName() + "\n学号:" + this.getStudentNo() + "\n性别:"
                + this.getStudentSex() + "\n年龄:" + this.getStudentAge() + "\n所报专业名称:" + sub1.getSubjectName()
                + "\n学制年限:"+sub1.getSubjectLife();
        return str;

    }
}

学科类

package com.alan.model;

public class Subject {

    // 成员属性:学科名称、学科编号、学制年限、选课学生数组、报名选修的学生个数
    private String subjectName;
    private String subjectNo;
    private int subjectLife;
    private Student[] myStudents;
    private int studentNum;
    

    // 无参构造方法,定义一下,防止出现意外的错误。
    public Subject() {

    }

    // 带参构造方法 对学科名称、学科编号、学制年限赋值
    public Subject(String subjectName, String subjectNo, int subjectLife) {

        this.setSubjectName(subjectName); // 尽量采用此种赋值方式,而不用this.subjectName=subjectName
        this.setSubjectNo(subjectNo); // 因为set方法中有时候会包含一些逻辑校验
        this.setSubjectLife(subjectLife);
    }
    
    // 带参构造方法 对全部属性赋值
    public Subject(String subjectName, String subjectNo, int subjectLife,Student[] myStudent) {

        this.setSubjectName(subjectName); // 尽量采用此种赋值方式,而不用this.subjectName=subjectName
        this.setSubjectNo(subjectNo); // 因为set方法中有时候会包含一些逻辑校验
        this.setSubjectLife(subjectLife);
        this.setMyStudents(myStudent);
    }

    /**
     * 获取选修专业学生信息,如果保存学生信息的数组没有被初始化,则初始化长度为200
     * @return 保存学生信息的数组
     */
    public Student[] getMyStudents() {
        if(myStudents == null)
            myStudents = new Student[200];
        return myStudents;
    }

    public void setMyStudents(Student[] myStudents) {
        this.myStudents = myStudents;
    }

    public String getSubjectName() {
        return subjectName;
    }

    public void setSubjectName(String subjectName) {
        this.subjectName = subjectName;
    }

    public String getSubjectNo() {
        return subjectNo;
    }

    public void setSubjectNo(String subjectNo) {
        this.subjectNo = subjectNo;
    }

    public int getSubjectLife() {
        return subjectLife;
    }

    // 设置学制年限,必须大于0
    public void setSubjectLife(int subjectLife) {
        if (subjectLife <= 0)
            return;
        this.subjectLife = subjectLife;
    }
    public int getStudentNum() {
        return studentNum;
    }

    public void setStudentNum(int studentNum) {
        this.studentNum = studentNum;
    }

    /**
     * 专业介绍的方法
     * @return 专业介绍的相关信息 专业名称、专业编号、学制年限
     */
    public String info() {
        String str = "专业信息如下: \n" + "专业名称:" + this.getSubjectName() + "\n专业编号:" + this.getSubjectNo() + "\n学制年限:"
                + this.getSubjectLife();
        return str; 
    }
    
    public void addStudent(Student stu) {
        
        //1、将学生保存到数组中
        for(int i=0;i<this.getMyStudents().length;i++) {
            
            if(this.getMyStudents()[i]==null) {
                this.getMyStudents()[i] = stu;
                //2、将学生的个数保存到studentNum中
                this.studentNum = i+1;
                return;
            }
        }
    }

}

测试

package com.alan.test;

import com.alan.model.Student;
import com.alan.model.Subject;

public class NewTest {

    public static void main(String[] args) {

        
        Subject sub1 = new Subject("计算机科学与应用","J0001",4);
        System.out.println(sub1.info());
        System.out.println("=======================");
        Student stu1 = new Student("S01","张三","男",58,sub1);
        System.out.println(stu1.introduction());
        System.out.println("=======================");
        Student stu2 = new Student("S02","李四","男",19,sub1);
        System.out.println(stu2.introduction("计算机科学与技术", 4));
        System.out.println("=======================");
        Student stu3 = new Student("S03","王五","女",17,sub1);
        System.out.println(stu3.introduction(sub1));
        
        System.out.println("=======================");
        sub1.addStudent(stu1);
        sub1.addStudent(stu2);
        sub1.addStudent(stu3);
        
        System.out.println("学生的总数为:"+sub1.getStudentNum());
    }

}

四、Java继承


方法重写

1、子类重写父类的方法
2、方法名相同、参数列表相同(参数顺序、个数、类型),方法返回值相同
3、方法的访问修饰符是允许有变化的,但是访问范围要大于等于父类的访问范围)
4、与方法参数名无关(string name)可以换成(string month)


访问修饰符

super关键字


继承的初始化顺序

Object类


final关键字

注释简介

快捷键 option+/
@Override 给编译器看的,编译之后注解就没有用了。

五、Java设计模式

image.png

单例模式

package com.alan.singleton;

//饿汉式:创建对象实例的时候直接初始化
public class SingletonOne {

    //1、创建类中的私有构造
    private SingletonOne() {
        
    }
    
    //2、创建该类型的私有静态实例
    private static SingletonOne instance = new SingletonOne();
    
    
    //3、创建公有静态方法返回静态实例对象
    public static SingletonOne getInstance() {
        return instance;
    }
    
    
}

测试


import com.alan.singleton.SingletonOne;

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        //  SingletonOne one = new SingletonOne();  构造方法已经私有化,这种方式不允许
        
        SingletonOne one = SingletonOne.getInstance();
        SingletonOne two = SingletonOne.getInstance();

        System.out.println(one);
        System.out.println(two);  //所有的引用都会指向同一个对象

        
    }

}

package com.alan.singleton;

// 懒汉式单例模式
public class SingletonTwo {

    // 1、创建私有构造方法
    private SingletonTwo() {
        
    }
    
    // 2、创建私有静态实例,静态的实例被共享,一定需要此修饰符
    private static SingletonTwo instance = null;
    
    // 3、创建静态公有方法返回静态实例对象
    public static SingletonTwo getInstance() {
        if(instance == null)
            instance = new SingletonTwo();
        return  instance;
    }
}
image.png

六、多态

封装和继承都是为多态准备的,是最核心也是最重要的概念。
多态的必要条件:
1、继承
2、重写
3、父类引用指向子类对象

向上转型

package com.alan.test;

import com.alan.animal.Animal;
import com.alan.animal.Cat;
import com.alan.animal.Dog;

public class Test {

    public static void main(String[] args) {
        
        Animal one = new Animal();
        /* 向上转型、隐式转型、自动转型
        父类引用指向子类的对象,可以调用子类重写父类的方法,以及父类派生的方法,无法调用子类独有方法
        小类转型为大类
        */
        Animal two = new Cat();
        Animal three = new Dog();
        one.eat();
        two.eat();
        three.eat();
    }
}

向下转型

package com.alan.test;

import com.alan.animal.Animal;
import com.alan.animal.Cat;
import com.alan.animal.Dog;

public class Test {

    public static void main(String[] args) {
        
        Animal one = new Animal();
        /* 向上转型、隐式转型、自动转型
        父类引用指向子类的对象,可以调用子类重写父类的方法,以及父类派生的方法,无法调用子类独有方法
        小类转型为大类
        */
        Animal two = new Cat();
        Animal three = new Dog();
        
        one.eat();
        two.eat();
        three.eat();
        System.out.println("============================");
        
        /*向下转型、强制类型转换
         * 子类引用指向父类对象、此处必须进行强转,可以调用子类特有的方法
         * 必须满足转换条件才能转换
         * */
        Cat temp = (Cat)two;
        temp.eat();
        temp.run();
        
    }

}

抽象类

抽象方法

不允许包含方法体;子类中需要重写父类的抽象方法。否则,子类也要设置为抽象类。

接口

package com.alan.tel;
/**
 * 具有上网功能的接口
 * @author alan
 *
 */

//接口可以设置的访问修饰符:public 默认

public interface INet {
    //接口中抽象方法可以不写abstract关键字,访问修饰符默认为public
    public void network();
    
    //default:默认方法 可以带方法体  jdk1.8之后新增的方法
    //可以在实现类中重写,并可以通过接口的引用调用
    default public void connection() {
        System.out.println("我是接口中的默认方法");
    }
    
    //static:静态方法 可以带方法体  jdk1.8之后新增的方法
    //不可以在实现类中重写,可以通过接口调用
    static void stop() {
        System.out.println("我是接口中的静态方法");
    }
    
    //接口中可以包含常量,默认会自动加上public final static
    
    int TEMP =20;
}

接口也可以实现继承关系,并且可以继承多个父接口

内部类

在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。
与之对应,包含内部类的类叫外部类。
分为:1、成员内部类 2、静态内部类 3、方法内部类 4、匿名内部类

package com.alan.people;


//外部类
public class Person {
    
    int age;
    
    public Heart getHeart() {
        
        return new Heart();
    }
    
    //成员内部类
    /*
     * 1、内部类在外部使用时,无法直接实例化,需要借由外部类信息才能完成实例化
     * 2、内部类的访问修饰符,可以任意,但是访问范围会受到影响
     * 3、内部类可以直接访问外部类的成员;如果出现同名属性,优先访问内部类中的定义
     * 4、可以使用外部类.this.成员方式,访问外部类中的同名信息
     * 5、外部类访问内部类信息,需要通过内部类实例,无法直接访问。
     * 6、内部类编译后.class文件命名:外部类$内部类.class
     * */
    class Heart{
        
        public String beat() {
            return "心脏在跳动";
        }
    }

}
package com.alan.people;

public class PersonTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        Person lili = new Person();
        
        //获取内部类对象实例,方式1:new 外部类. new 内部类
        Person.Heart myheart = new Person().new Heart();
        System.out.println(myheart.beat());

        //获取内部类对象实例,方式2:外部类对象.new 内部类
        myheart = lili.new  Heart();
        System.out.println(myheart.beat());

        //获取内部类对象实例,方式3:外部类调用方法返回内部类
        myheart = lili.getHeart();
        System.out.println(myheart.beat());

    }

}
上一篇 下一篇

猜你喜欢

热点阅读