JAVA面向对象(中)

一、包

1.1 包的作用是什么?

  • 按照不同的主题分类管理我们的类 => 此时你可以把包当成文件夹的概念,不同文件夹放不同主题的类

  • 避免类的重名 => 包相当于类的前缀,类的全名称是 包.类名,例如:java.util.Scanner, java.lang.String, java.lang.Math, java.lang.System

  • 结合权限修饰符,限定某些类或成员的可见性范围

one包的类
package one;
​
//注意:这里的类前面 故意 没有加 public
class DemoOne {
    public static void m(){
        System.out.println("静态方法m");
    }
}

two包的测试类
package two;
​
import one.DemoOne;
​
public class TestDemoOne {
    public static void main(String[] args) {
        DemoOne d = new DemoOne();
        DemoOne.m();
    }
}
//以上代码会报错

1.2 如何声明包?

1、在源代码中的package语句

package 包名;

这句语句必须在源文件的首行。我们不会手动写这句话,而且由IDEA自动加这句话。

包名的命名规范:

  • 所有单词都小写,单词直接使用 . 分割,每一个.代表一个层级。

  • 习惯上用公司域名倒置 + 主题名 来命名,例如: com.atguigu.xxx

    • 一级域名:com商业性的公司, org非盈利性组织,edu教育机构等

2、通过IDEA怎么创建包

3、在包下面如何创建类

1.3 如何跨包使用类

前提:这个类必须是跨包可以用的,即public。

方式一:使用全名称

方式二:import 包名.类名; 然后代码中使用类的简名称

Java中规定使用java.lang包下的类,不需要import语句,就可以直接使用简名称。

导包语句的写法:

import 包名.类名;
import 包名.*;
com.atguigu.bean包的其他类
package com.atguigu.bean;
​
public class Student {
}
package com.atguigu.bean;
​
public class Teacher {
}
package com.atguigu.bean;
​
public class Employee {
}
package com.atguigu.bean;
​
public class TestStudent {
    public static void main(String[] args) {
        Student s = new Student();//使用同一个包的类不需要导包
    }
}
com.atguigu.pck包的测试类
package com.atguigu.pck;
​
/*import com.atguigu.bean.Employee;
import com.atguigu.bean.Student;
import com.atguigu.bean.Teacher;*/
​
import com.atguigu.bean.*;
​
import java.util.Scanner;
/*import java.lang.String;
import java.lang.System;*/
​
public class TestImport {
    public static void main(String[] args) {
        //java.util.Scanner input = new java.util.Scanner(System.in);//使用类的全名称
​
        Scanner input = new Scanner(System.in);
​
        input.close();
​
        //使用com.atguigu.bean包下的Student类
        Student s = new Student();
        Teacher t = new Teacher();
        Employee e = new Employee();
    }
}

1.4 静态导入(了解)

package com.atguigu.pck;
​
import  static java.lang.Math.*;
​
public class TestStaticImport {
    public static void main(String[] args) {
        //调用Math类的一些静态方法,静态常量
/*        System.out.println(Math.PI);//圆周率
        System.out.println(Math.random());//随机产生[0,1)的小数
        System.out.println(Math.sqrt(9));//求平方根
        System.out.println(Math.max(5,6));//求最大值
        System.out.println(Math.pow(5,6));//求5的6次方*/
​
        System.out.println("======================");
        System.out.println(PI);//圆周率
        System.out.println(random());//随机产生[0,1)的小数
        System.out.println(sqrt(9));//求平方根
        System.out.println(max(5,6));//求最大值
        System.out.println(pow(5,6));//求5的6次方
    }
}

二、类的第三个成员:构造器(非常重要)

2.1 构造器的作用

  • 构造器与关键字new一起,用来创建对象。换句话说,new关键字后面的就是构造器。

  • 在new对象时,要为对象的属性初始化。如果没有指定值,属性就是默认值。

2.2 构造器的特点

(1)每一个类都有构造器

(2)如果这个类没有==“手动”==编写任何构造器的话,那么编译器就会==“自动”==给你这个类添加默认的无参构造

但是,如果你==“手动”编写==了任何构造器,那么编译器就==不会再“自动”==给你加无参构造了,如果需要无参构造,就必须自己==手动添加==。

(3)构造器也可以手动编写,并且可以重载

(4)构造器的名称必须与类名完全一致,包括大小写。

(5)构造器没有返回值类型。不能写返回值类型(void等)

(6)构造器的修饰符只能是public、protected、缺省、private,不能有其他修饰符,例如:static,final等

构造器的语法格式:

【修饰符】 构造器名称(【形参列表】){
    【构造器的方法体;】
}
​
//一共4个部分,没有返回值类型

注意:构造器与普通方法非常相似,不同的是,构造器没有返回值类型。很多程序员,会把构造器称为构造方法,但是笔记中,一般叫构造器,避免初学者搞混淆。

2.3 构造器示例代码

package com.atguigu.constructor;
​
public class Rectangle {//矩形
    //成员变量,属性,实例变量
    public double length;
    public double width;
​
    public Rectangle(double chang, double kuan){//手动写的有参构造
        length = chang;
        width = kuan;
    }
    public Rectangle(){//手动写的无参构造
​
    }
​
    public String getInfo(){
        return "长:" + length +",宽:" + width;
    }
​
}
 
package com.atguigu.constructor;
​
public class TestRectangle {
    public static void main(String[] args) {
        //调用无参构造创建了Rectangle类的对象
        Rectangle r1 = new Rectangle();
​
        //调用有参构造创建了Rectangle类的对象
        Rectangle r2 = new Rectangle(8, 5);
​
​
        //调用r1和r2对象的getInfo方法
        System.out.println(r1.getInfo());//长:0.0,宽:0.0
        System.out.println(r2.getInfo());//长:8.0,宽:5.0
    }
}
​

2.4 构造器的快捷键

2.5 关键字this

1、this.属性

2、this() 或 this(实参列表)

this() 或 this(实参列表):都必须在构造器的首行。

  • this():调用本类的无参构造

  • this(实参列表):调用本类的有参构造,至于调用哪个有参构造,要看参数列表的匹配情况

package com.atguigu.constructor;
​
public class Employee {
    //属性
    public String name;
    public String tel;
    public double salary;
    public int age;
    public String address;
​
    //用快捷键生成构造器,Alt + Insert ,部分同学的键盘模式需要同时按Fn
    //在类的里面,不要在类的外面按快捷键,也不要在方法体里面按快捷键
    public Employee() {
    }
    public Employee(String name, String tel, double salary, int age, String address) {
        /*this.name = name;
        this.tel = tel;
        this.salary = salary;*/
        this(name,tel,salary);
        this.age = age;
        this.address = address;
//        this(name,tel,salary);//错误,必须在构造器首行
    }
    public Employee(String name, String tel, double salary) {
//        this();//这类写它没有意义,去掉它
        this.name = name;
        this.tel = tel;
        this.salary = salary;
    }
}
package com.atguigu.constructor;
​
public class TestEmployee {
    public static void main(String[] args) {
        //分别用3种方式,创建对象
        Employee e1 = new Employee();
​
        Employee e2 = new Employee("张三","10086",15000);
​
        //快捷键,查看调用的构造器或方法的形参列表,在()里面按Ctrl + P
        Employee e3 = new Employee("李四","10010",16000,25,"上海");
​
//        Employee e4 = new Employee("王五",17800);//报错
        
        
        //如果要看到对象的信息,必须自己再加打印语句
    }
}

三、封装

3.1 什么是封装?

封装是面向对象的基本特征之一。

生活中,大家收发快递,都有包裹。想一想快递为什么要用包裹?

  • 避免损坏 => 为了安全

  • 保护隐私 => 为了信息安全

  • 便于运输 => Java中便于使用

类中的封装:

  • 为了安全,可以让外界按照我指定的方式(通常就是get/set等方法)来操作属性。例如:通常会将属性进行私有化。

  • 为了方便使用,可以将重复性的代码封装为方法,实现重复使用的效果。一个方法封装了一个功能。

package com.atguigu.encapsolation;
​
public class Student {
    //属性
    //public:公共的,随意可见的
    //private:私有的,只有本类可以“直接”使用
    private String name;
    private int score;//成绩属性
//    public int grade;//故意对比,写了两个成绩属性
​
    public String getName(){
        return name;
    }
    public void setName(String name){
        this.name = name;
    }
​
    public int getScore(){
        return score;
    }
    public void setScore(int score){
        if(score>=0 && score<=100) {
            this.score = score;
        }else{
            System.out.println("成绩必须在[0,100]之间");
        }
    }
}
package com.atguigu.encapsolation;
​
public class TestStudent {
    public static void main(String[] args) {
        Student s1 = new Student();
        /*s1.name = "张三";
        s1.score = 89;*/
        //报错,name和score是pirvate私有的属性,在测试类中不能直接操作它
​
        s1.setName("张三");
        System.out.println("姓名:" + s1.getName());
        s1.setScore(89);
        System.out.println("成绩:" + s1.getScore());
​
/*        int chengJI = -10;
        if(chengJI>=0 && chengJI<=100) {
            s1.grade = chengJI;
        }
​
        Student s2 = new Student();
        int chengJI2 = -10;
        if(chengJI2>=0 && chengJI2<=100) {
            s2.grade = chengJI2;
        }*/
    }
}

3.2 属性私有化

1、属性前面用private修饰

【修饰符】 class 类名{
    private 数据类型 属性名1;
    private 数据类型 属性名2;
    private 数据类型 属性名3;
}

2、会为属性提供get/set

  • get方法:当我们调用get方法时,可以==得到==一个值。

  • set方法:当我们调用set方法时,可以==修改==一个属性的值。

  • get/set方法是有快捷键自动生成:Alt + Insert

    • boolean类型的get方法的开头单词从get换成了is

    • 静态变量的get/set方法也是静态的,而且在静态方法中,局部变量(这里是形参)与静态变量重名,需要加“类名.静态变量”进行区分。

    • 实例变量的get/set方法也是非静态的,在非静态方法中,局部变量(这里是形参)与实例变量重名,需要加“this.实例变量”进行区分。

【修饰符】 class 类名{
    private 数据类型1 属性名1;
    private 数据类型 属性名2;
    private 数据类型 属性名3;
    
    //为属性1 提供了 一对get/set方法
    public 数据类型1 get属性名1(){
        return 属性名1;
    }
    public void set属性名1(数据类型1 形参名1){
        this.属性名1 = 形参名1;
    }
    
    //为属性2 提供了 一对get/set方法
    public 数据类型2 get属性名2(){
        return 属性名2;
    }
    public void set属性名2(数据类型2 形参名2){
        this.属性名2 = 形参名2;
    }
    
    //为属性3 提供了 一对get/set方法
    public 数据类型3 get属性名3(){
        return 属性名3;
    }
    public void set属性名3(数据类型3 形参名3){
        this.属性名3 = 形参名3;
    }
    
    /*
    //一般很少用下面这个set方法,同时为3个属性赋值,这就表示一旦修改,需要同时修改3个属性。复用性比较差。
    public void setInfo(数据类型1 形参名1,  数据类型2 形参名2, 数据类型3 形参名3){
        this.属性名1 = 形参名1;
        this.属性名2 = 形参名2;
        this.属性名3 = 形参名3;
    }*/
}

3、get/set与构造器的区别

  • 构造器:用来创建对象的,可以在创建对象的同时给实例变量初始化

  • get/set:在对象创建之后,用来获取/修改单个属性的值

4、示例代码

package com.atguigu.encapsolation;
​
public class Employee {
    //属性,私有化了,public -> private
    private String name;
    private String tel;
    private double salary;
    private int age;
    private String address;
    private boolean marry;//是否已婚
    private static String company;//公司名   静态变量
​
    //构造器 快捷键 Alt + Insert
    public Employee() {
    }
​
    public Employee(String name, String tel, double salary, int age, String address, boolean marry) {
        this.name = name;
        this.tel = tel;
        this.salary = salary;
        this.age = age;
        this.address = address;
        this.marry = marry;
    }
​
    //方法
    //get/set 快捷键 Alt + Insert
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public String getTel() {
        return tel;
    }
​
    public void setTel(String tel) {
        this.tel = tel;
    }
​
    public double getSalary() {
        return salary;
    }
​
    public void setSalary(double salary) {
        this.salary = salary;
    }
​
    public int getAge() {
        return age;
    }
​
    public void setAge(int age) {
        this.age = age;
    }
​
    public String getAddress() {
        return address;
    }
​
    public void setAddress(String address) {
        this.address = address;
    }
​
    //对于boolean类型的属性,get方法的开头单词从get换成is
    public boolean isMarry() {
        return marry;
    }
​
    public void setMarry(boolean marry) {
        this.marry = marry;
        //当局部变量(这里是形参)与实例变量重名了,需要在非静态方法或构造器中使用 “this.实例变量”进行区别
    }
​
    public static String getCompany() {
        return company;
    }
​
    public static void setCompany(String company) {
        Employee.company = company;
        //当局部变量(这里是形参)与静态变量重名了,需要在静态方法中使用 “类名.静态变量”进行区别
    }
​
    public String getInfo(){
        return "姓名:" + name +",电话:" + tel
                +",薪资:" + salary +",年龄:" + age +",地址:" + address
                +",是否已婚:" + (marry?"是":"否")
                +",公司名:" + company;
    }
}
​
package com.atguigu.encapsolation;
​
public class TestEmployee {
    public static void main(String[] args) {
        Employee.setCompany("尚硅谷");
​
        Employee e = new Employee("张三","10086",18000,23,"北京",true);
        System.out.println(e.getInfo());
​
        //如果对象已经创建好的情况下,要单独修改某个属性值,就要调用它的set方法
        //例如给e对象涨薪20%
        e.setSalary(e.getSalary() * 1.2);
​
        //如果想要单独获取某个属性值,调用它对应get方法
        System.out.println("e对象目前的薪资:" + e.getSalary());
    }
}
​

3.3 权限修饰符

1、可见性范围

权限修饰符,又称为访问控制修饰符。用于限定类或成员的可见性范围。下面这张表格说明了几种权限修饰符的可见性范围:

本类同一个包的其他类中其他包的子类中其他包的非子类中
private×××
缺省(不写)××
protected×
public

2、示例代码

com.atguigu.first包的类
package com.atguigu.first;
​
public class Father {
    private int a;//private,私有的
    int b; //不写权限修饰符,称为缺省,默认的
    protected int c; //protected,受保护的
    public int d; //public,公共的
​
    public void m(){
        //在本类中,只要不违反静态不能访问非静态的原则,本类的所有成员,无论哪种权限修饰符,都是可以直接使用的。
        System.out.println("a = " + a);
        System.out.println("b = " + b);
        System.out.println("c = " + c);
        System.out.println("d = " + d);
    }
}

 

package com.atguigu.first;
​
public class TestFather {
    public static void main(String[] args) {
        Father father = new Father();
//        System.out.println("father.a = " + father.a);//错误,私有的不能跨类使用
        System.out.println("father.b = " + father.b);
        System.out.println("father.c = " + father.c);
        System.out.println("father.d = " + father.d);
    }
}
 
com.atguigu.second包的类
package com.atguigu.second;
​
import com.atguigu.first.Father;
​
//Son类现在是Father类的子类
public class Son extends Father {
    public void fun(){
//        System.out.println("a = " + a);//错误的,私有的不允许跨类
//        System.out.println("b = " + b);//错误的,缺省的不允许跨包
        System.out.println("c = " + c);//可以,受保护的,只要是在本子类中就可以访问所有父类的protected成员
        System.out.println("d = " + d);
    }
}
package com.atguigu.second;
​
import com.atguigu.first.Father;
​
public class TestFatherInOtherPackage {
    public static void main(String[] args) {
        Father father = new Father();
//        System.out.println("father.a = " + father.a);//错误,私有的不能跨类使用
//        System.out.println("father.b = " + father.b);//错误,缺省不能跨包使用
//        System.out.println("father.c = " + father.c);//错误,受保护如果跨包的话,必须是在子类中
        System.out.println("father.d = " + father.d);
    }
}

3、权限修饰符分别可以修饰什么

  • class前面可以出现的权限符是:public 或 缺省不写

  • 成员(成员变量、成员方法、构造器)前面:四种都可以加

  • 局部变量:啥都不可以加(四种权限修饰符都不可以,static也不可以),除了final

package com.atguigu.encapsolation;
​
public class Demo {//公共的类
    //属性的前面,四种权限修饰符都可以
    private int a;
    int b;
    protected int c;
    public int d;
​
    //构造器的前面,四种权限修饰符都可以
//    public Demo(){}
//    Demo(){}
//    protected Demo(){}
    private Demo(){}
​
    //方法的前面,四种权限修饰符都可以
    public void m1(){
​
    }
    void m2(){
​
    }
    protected void m3(){
​
    }
    private void m4(){
​
    }
​
}
/*
class Demo {//类的权限修饰符是缺省
​
}*/
​
/*private class Demo {//类的权限修饰符是私有的,错误的
​
}*/
/*
protected class Demo {//类的权限修饰符是受保护的,错误的
​
}*/
​
package com.atguigu.encapsolation;
​
public class TestVariable {
    static int a;//静态变量
    int b;//实例变量
​
    public void method(int d){//形参也是局部变量
        int c;//局部变量,前面不可以加static,pubilc,protected,private等
    }
}
​

3.4 标准Javabean

bean:豆子

Javabean:Java豆,因为Java的名称来源于 产咖啡的爪哇岛,所以Java类也被称为Java豆,咖啡豆。

这里讲的标准Javabean是指一种写Java类的规范:

  • 属性私有化

  • 提供get/set方法

  • 提供无参构造

  • 可以有选择添加有参构造(自选)

  • 重写toString等(明天讲)

package com.atguigu.version3;
​
public class Teacher {
    private String name;
    private double salary;
​
    public Teacher() {
    }
    public Teacher(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public double getSalary() {
        return salary;
    }
    public void setSalary(double salary) {
        this.salary = salary;
    }
}

3.5 练习题

练习题1

(1)定义矩形类Rectangle,

  • 声明实例变量长和宽,全部私有化private,

  • 提供相应的get/set方法,如果set方法的参数值<=0,则提示矩形的长和宽必须是正数

  • 声明public double area(),返回矩形面积

  • 声明public double perimeter():返回矩形的周长

  • 声明public String getInfo():返回矩形的长、宽、面积、周长信息

(2)测试类的main中创建一个可以装3个矩形对象的数组,并调用set方法为对象的属性赋值,依次长是8,7,6,宽是2,3,4

  • 遍历输出矩形对象数组

  • 按照矩形对象的length属性值从小到大排序后,遍历输出矩形对象数组

  • 按照矩形对象的面积从小到大排序后,遍历输出矩形对象数组

矩形类
package com.atguigu.exer3;
​
public class Rectangle {
    private double length;
    private double width;
    
    public Rectangle() {
    }
​
    public Rectangle(double length, double width) {
        if(length <= 0 || width <= 0){
            System.out.println("矩形的长和宽必须是正数");
            return;
        }
        this.length = length;
        this.width = width;
    }
​
    public double getLength() {
        return length;
    }
​
    public void setLength(double length) {
        if(length <= 0){
            System.out.println("矩形的长必须是正数");
            return;
        }
        this.length = length;
    }
​
    public double getWidth() {
        return width;
    }
​
    public void setWidth(double width) {
        if(width <= 0){
            System.out.println("矩形的宽必须是正数");
            return;
        }
        this.width = width;
    }
​
    public double area(){
        return length * width;
    }
​
    public double perimeter(){
        return 2 * (length + width);
    }
    
    public String getInfo() {
        return "长:" + length + ",宽:" + width + ",面积:" + area() +",周长:" + perimeter();
    }
}
​
矩形测试类
package com.atguigu.exer3;
​
public class TestRectangle {
    public static void main(String[] args) {
        Rectangle[] arr = new Rectangle[3];
        arr[0] = new Rectangle();//调用无参构造创建矩形对象
        arr[0].setLength(8);//调用set方法为 属性赋值
        arr[0].setWidth(2);//调用set方法为 属性赋值
​
        arr[1] = new Rectangle(7,3);//调用有参构造创建矩形对象
​
        arr[2] = new Rectangle(6,4);//调用有参构造创建矩形对象
​
        System.out.println("原始数据:");
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i].getInfo());
        }
​
        System.out.println("按照length从小到大排序:");
        for (int i = 1; i < arr.length; i++) {
            for (int j = 0; j < arr.length - i; j++) {
                if (arr[j].getLength() > arr[j + 1].getLength()) {
                    Rectangle temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i].getInfo());
        }
​
        System.out.println("按照面积从小到大排序:");
        for (int i = 1; i < arr.length; i++) {
            for (int j = 0; j < arr.length - i; j++) {
                if (arr[j].area() > arr[j + 1].area()) {
                    Rectangle temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
​
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i].getInfo());
        }
    }
}

练习题2

(1)定义三角形类Triangle,

  • 声明实例变量a,b,c,代表三角形三条边,全部私有化private,

  • 提供每条边的get方法,

  • 提供public void setBases(double a, double b, double c):要求参数a,b,c的值必须大于等于0,且满足三角形三边关系要求(即任意两边之后大于第三边),否则提示错误信息

  • 声明public double area(),返回三角形面积

  • 声明public double perimeter():返回三角形周长

  • 声明public String getInfo():返回三角形的三条边,面积和周长

(2)测试类的main中创建一个三角形对象,并调用相应方法

三角形类
package com.atguigu.exer4;
​
public class Triangle {
    private double a;
    private double b;
    private double c;
​
    public Triangle() {
    }
​
    public Triangle(double a, double b, double c) {
        /*this.a = a;
        this.b = b;
        this.c = c;*/
        setBase(a,b,c);
    }
​
    public double getA() {
        return a;
    }
​
    public double getB() {
        return b;
    }
​
    public double getC() {
        return c;
    }
​
    public void setBase(double a, double b, double c){
        if(a>0 && b>0 && c>0 && a+b>c && b+c>a && a+c>b){
            this.a = a;
            this.b = b;
            this.c = c;
        }else{
            System.out.println("三角形的三边必须是正数,且任意两边之和大于第三边");
//            throw  new IllegalArgumentException(a+","+b+","+c +"不符合三角形要求");
        }
    }
​
    /*public void setBase(double a, double b, double c){
        if(a<=0 || b<=0 || c<=0 || a+b<=c || b+c<=a || a+c<=b){
            System.out.println("三角形的三边必须是正数,且任意两边之和大于第三边");
            return;//提前结束方法的执行
        }
        this.a = a;
        this.b = b;
        this.c = c;
    }*/
​
    public double area(){
        double p = (a+b+c)/2;
        return Math.sqrt(p*(p-a)*(p-b)*(p-c));
        //海伦公式
    }
​
    public double perimeter(){
        return a + b+c;
    }
​
    public String getInfo(){
        return "a:" + a + ",b:" + b + ",c=" +c +",面积:" + area() +",周长:" + perimeter();
    }
}
​

三角形的测试类
package com.atguigu.exer4;
​
public class TestTriangle {
    public static void main(String[] args) {
        Triangle t = new Triangle();
        t.setBase(3,4,5);
        System.out.println(t.getInfo());
​
        System.out.println("===================");
​
        Triangle t2 = new Triangle(1,2,5);
        System.out.println(t2.getInfo());
    }
}
  • 46
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值