java语言--------javaSE之面向对象

面向对象

构造方法的概述与格式

构造方法的概述和作用:

创建对象,给对象中的成员进行初始化

构造方法格式特点:
  • 方法名与类名相同

  • 没有返回值类型,不用void

  • 没有具体的返回值

构造方法的重载(创建不同的用户对象):
  • 如果方法构造中形参名与属性名相同时,需要使用this关键字区分属性与形参。
this关键字:
  • this的作用是在类中通过this访问自身的属性和方法。
String name = "李四";                         //定义一个成员变量name             
public Student(String name) {                //定义一个参数(局部变量)name
        this.name = name;                    //将局部变量的值传递给成员变量
    }
 /**  有一个成员变量name,同时在方法中也有一个形参叫name,然后将方法中的形参传递给成员变name;this.name代表的就是对象中的成员变量,又叫做对象的属性,而后面的name则是方法的形式参数,this.name=name就是将形式参数的值传递给成员变量*/
public:
  • 公共的,可以被同一项目下的任何类所调用,一般用于对外的情况。
private:
  • 只为类本身提供。是一种封装的体现。
get,set方法:
  • get和set方法一般是用于封装类的属性,将属性私有化,然后通过set 和 get 方法。
实例(学生类)
public class Student { 
    private String name ;                        //设私有变量name
    private int age;                             //设私有变量age
    public void setName(String name) {           //定义set方法
        this.name = name;                        //将局部变量的值传递给成员变量
    }
public String getName(){                         //定义get方法
        return name;
}
    public void setAge(int age) {
        this.age = age;
    }
    public int getAge() {
        return age;
    }
    public void show(){
        System.out.println("姓名:"+name+"=====年龄:"+age);
    }
}
public class MyTest {
    public static void main(String[] args) {

        Student s = new Student();                  //创建对象
        s.setName("张三");                           //调用set方法并传参张三给name
        s.setAge(50);                               //调用set方法并传参50给age
        s.show();
    }
}
                       运行结果:

                       姓名:张三=====年龄:50
 /**该类中有name,age是私有变量,然后我定义setage()、getage()这两个方法,通过这两个方法来实现对name,age的操作。main函数中使用调用setage方法并传参(张三),然后setage方法将张三设置给了name,调用setage方法并传参(50),然后setage方法将50设置给了age;然后main函数使用getage方法获取name和age的值。所以输出结果为 张三,50 。通过set和get方法间接地操作这些变量,这样就能提高域变量的安全性,同时又保证了域变量的封装型。*/

创建一个对象的步骤

  • Student s=new Student();

(1):加载Student.class文件进内存
(2):在栈内存为s开辟空间
(3):在堆内存为学生对象开辟空间
(4):对学生对象的成员变量进行默认初始化
(5):对学生对象的成员变量进行显示初始化
(6):通过构造方法对学生对象的成员变量赋值
(7):学生对象初始化完毕,把对象地址赋值给s变量

static关键字:

​ static关键字,告知编译器main函数是一个静态函数。也就是说main函数中的代码是存储在静态存储区的,静态方法在内存中的位置是固定的,即当定义了类以后这段代码就已经存在了。如果main()方法没有使用static修饰符,那么编译不会出错,但是如果你试图执行该程序将会报错,提示main()方法不存在。因为包含main()的类并没有实例化(即没有这个类的对象),所以其main()方法也不会存。而使用static修饰符则表示该方法是静态的,不需要实例化即可使用。

1.static 修饰的域,我们叫静态域,它是归类所有的,被所有对象所共享,只有一个
2.static修饰的区块,域只会初始化一次
3.static修饰的域或方法,可以直接通过类的名字加上.进行调用
4.static修饰的方法内不能直接使用非静态成员

实例:

public  lass Person {
    public String name;
    //static 静态的,可以修饰成员变量和成员方法,修饰成员变量,
    // 此变量就为一个共享变量,会被这个类的所有对象,所共享。
    public static String country = "中国";

}
public class MyTest {
    public static void main(String[] args) {     //静态的变量,通过类名直接调用,不需要new对象。
        Person.country="美国";
        Person p1 = new Person();
        p1.name = "张三";                        
        Person p2 = new Person();
        p2.name = "李四";                       
        Person p3 = new Person();
        p3.name = "王五";                       
        //让多个对象,去共享国籍这个数据。
        System.out.println(p1.name);
        System.out.println(p1.country);

        System.out.println("======================");

        System.out.println(p2.name);
        System.out.println(p2.country);

        System.out.println("======================");

        System.out.println(p3.name);
        System.out.println(p3.country);

        System.out.println("=========================================");
        System.out.println(Person.country);

注意事项:

1.在静态方法中是没有this关键字的

2.静态是随着类的加载而加载,this是随着对象的创建而存在。静态比对象先存在。

3.静态方法只能访问静态的成员变量和静态的成员方法

简单记:静态只能访问静态,非静态可以访问静态的也可以访问非静态的

Math类的随机数功能

  • 打开jdk查询math类
案例演示:

需求:猜数字小游戏(数据在1-100之间)

public class shuzi {
    public static void main(String[] args) {
        int num = (int) (Math.random() * 100 + 1);
        for (int i = 1; i <= 10; i++) {
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入一个你要猜的整数 1---100");
            int userNum = sc.nextInt();
            if (userNum > num) {
                System.out.println("你猜大了");
            } else if (userNum < num) {
                System.out.println("你猜小了");
            } else {
                System.out.println("恭喜你,猜对了");
            }
        }
    }
}

代码块

  • 代码块概述
    在Java中,使用{}括起来的代码被称为代码块。

  • 代码块分类
    根据其位置和声明的不同,可以分为局部代码块,构造代码块,静态代码块,同步代码块(多线程讲解)

  • 常见代码块的应用
    a:局部代码块
    在方法中出现;限定变量生命周期,及早释放,提高内存利用率
    b:构造代码块

    ​ 在类中方法外出现;多个构造方法方法中相同的代码存放到一起,每次调用构造都执行,并且在构造方法前执行
    ​ c:静态代码块
    ​ 在类中方法外出现,加了static修饰
    ​ 在类中方法外出现,并加上static修饰;用于给类进行初始化,在加载的时候就执行,并且只执行一次。

案例(测试题)
	A:看程序写结果
	class Student {
		static {
			System.out.println("Student 静态代码块"); //3
		}
	{
		System.out.println("Student 构造代码块"); //4 6
	}
	
	public Student() {
		System.out.println("Student 构造方法");//5 7
	}
}

class StudentDemo {
	static {
		System.out.println("StudentDemo的静态代码块");  //1
	}
	
	public static void main(String[] args) {
		System.out.println("我是main方法"); //2
	
		Student s1 = new Student();
		Student s2 = new Student();
	}
}

继承

1.继承的基本格式: 通过extends关键字可以实现类与类的继承 ;

class 子类名 extends 父类名 {}

2.继承的概念:多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。

this与super关键字
  • this 代表的是本类对象的引用
  • super 代表的是父类存储空间的标识(可以理解成父类的引用,可以操作父类的成员)
  • this和super的使用
    a:调用成员变量
    this.成员变量 调用本类的成员变量
    super.成员变量 调用父类的成员变量
    b:调用构造方法
    this(…) 调用本类的构造方法
    super(…) 调用父类的构造方法
    c:调用成员方法
    this.成员方法 调用本类的成员方法
    super.成员方法 调用父类的成员方法

3.继承的注意事项

​ a:子类只能继承父类所有非私有的成员(成员方法和成员变量)
​ b:子类不能继承父类的构造方法,但是可以通过super关键字去访问父类构造方法。
​ c:不要为了部分功能而去继承

4.继承中成员变量的关系:

​ A:子类中的成员变量和父类中的成员变量名称不一样
​ B:子类中的成员变量和父类中的成员变量名称一样
​ 在子类中访问一个变量的查找顺序(“就近原则”)
​ a: 在子类的方法的局部范围找,有就使用
​ b: 在子类的成员范围找,有就使用
​ c: 在父类的成员范围找,有就使用
​ d:如果还找不到,就报错

5.继承中构造方法的关系:

子类中所有的构造方法默认都会访问父类中空参数的构造方法

因为子类会继承父类中的数据,可能还会使用父类的数据。
所以,子类初始化之前,一定要先完成父类数据的初始化。

每一个构造方法的第一条语句默认都是:super()

6.继承中成员方法的关系:

当子类的方法名和父类的方法名不一样的时候
当子类的方法名和父类的方法名一样的时候
通过子类调用方法:
a: 先查找子类中有没有该方法,如果有就使用
b:在看父类中有没有该方法,有就使用

案例
class Fu{
	public int num = 10;
	public Fu(){
		System.out.println("fu"); 
	}
}
class Zi extends Fu{
	public int num = 20;
	public Zi(){
		System.out.println("zi"); 
	}
	public void show(){
		int num = 30;
		System.out.println(num); //30
		System.out.println(this.num); //20
		System.out.println(super.num); //10
	}
}
class Test {
	public static void main(String[] args) {
		Zi z = new Zi();
		z.show();
	}
}
运行结果为:
fu  zi  30 20 10

方法重写

概念:Override;子类中出现了和父类中一模一样的方法声明(方法名,参数列表,返回值类型),也被称为方法覆盖,方法复写。

应用:当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法。
这样,即沿袭了父类的功能,又定义了子类特有的内容。

注意事项:

1.父类私有的方法子类不能重写
2.构造方法,静态方法,不参与重写。
3.子类重写父类方法时,方法的权限修饰符,不能比父类的低,要比父类的高,或者一样。
4.父类final修饰的方法子类不能重写。

方法重载:允许在一个类中定义多个同名方法,只有他们的参数列表不同(个数不同或数据类型不同)

重载和重写的区别

  • 作用范围:重写的作用范围是父类和子类之间;重载是发生在一个类里面
  • 参数列表:重载必须不同;重写不能修改
  • 返回类型:重载可修改;重写方法返回相同类型或子类
  • 抛出异常:重载可修改;重写可减少或删除,一定不能抛出新的或者更广的异常
  • 访问权限:重载可修改;重写一定不能做更严格的限制
案例
public class Animal {

    public void sleep(){
        System.out.println("睡觉");
    }
    public void eat(){
        System.out.println("吃饭");
    }
}
public class Cat extends Animal{
    @Override
    public void eat(){
        System.out.println("猫吃鱼");
    }

    //Ctrl+O 重写父类的方法
    @Override       //@Override 注解 作用:用来检测这个方法,是不是重写父类的。
    public void sleep() {
        System.out.println("猫白天睡觉");
    }

final关键字:

由于继承中有一个方法重写的现象,而有时候我们不想让子类去重写父类的方法.这对这种情况java就给我们提供了一个关键字: final

final关键字是最终的意思,可以修饰类,变量,成员方法。

A:final修饰特点
修饰类: 被修饰类不能被继承
修饰方法: 被修饰的方法不能被重写
修饰变量: 被修饰的变量不能被重新赋值,因为这个量其实是一个常量

多态

1.概念:某一个事物,在不同时刻表现出来的不同状态。

举例: Cat c=new Cat();
Animal a=new Cat();

2.多态的前提:

​ a:要有继承关系。
​ b:要有方法重写。 其实没有也是可以的,但是如果没有这个就没有意义。
​ c:要有父类引用指向子类对象。
​ 父 f = new 子();

3.多态中的成员访问特点:

​ a:成员变量
​ 编译看左边,运行看左边。
​ b:构造方法
​ 创建子类对象的时候,会访问父类的构造方法,对父类的数据进行初始化。
​ c:成员方法
​ 编译看左边,运行看右边。
​ d:静态方法
​ 编译看左边,运行看左边。
​ (静态和类相关,算不上重写,所以,访问还是左边的)

4.多态的好处:

  • 能够提高代码的复用性和维护性(靠继承保证)
  • 提高代码的扩展性。

5.多态的弊端以及多态中向上转型和向下转型

  • 多态的弊端:不能使用子类特有的功能
Fu fu = new Zi();  //向上转型:多态就是向上转型
  • 向下转型:把父类的引用强制转换为子类的引用。
//我们可以采用向下转型,那调用子类特有的功能
 System.out.println(fu.num); //200
 Zi zi= (Zi) fu; //把父类引用,向下转型为子类型。
 zi.hehe();
 System.out.println(zi.num);  //10
案例
public class MyTest {
    public static void main(String[] args) {
        //多态的弊端:不能调用子类特有的功能
        Fu fu = new Zi();  //向上转型:多态就是向上转型。

        fu.show();
        //多态,不能直接调用,子类特有的功能。
        //fu.hehe(); 报错。
       //我们可以采用向下转型,那调用子类特有的功能
        System.out.println(fu.num); //200
        Zi zi= (Zi) fu; //把父类引用,向下转型为子类型。
        zi.hehe();
        System.out.println(zi.num);  //10
    }
}
class Fu {
    int num=200;
    public void show() {
        System.out.println("fu Show");
    }
}

class Zi extends Fu {
    int num=10;
    @Override
    public void show() {
        System.out.println("zi Show");
    }
    public void hehe() {
        System.out.println("子类特有的方法");
    }
}

抽象类

  • 在java中使用abstract class来定义抽象类。
抽象类概述:

​ 猫狗案例,提取出了一个动物类。并且我们在前面也创建过了动物对象,其实这是不对的。
​ 为什么呢?因为,我说动物,你知道我说的是什么动物吗?只有看到了具体的动物,你才知道,这是什么动物。
​ 所以说,动物本身并不是一个具体的事物,而是一个抽象的事物。只有真正的猫,狗才是具体的动物。
​ 同理,我们也可以推想,不同的动物吃的东西应该是不一样的,所以,我们不应该在动物类中给出具体体现,而是应该给出一个声明即可。
​ 在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类。

抽象类特点

​ a:抽象类和抽象方法必须用abstract关键字修饰
​ 抽象类格式: abstract class 类名 {}
​ 抽象方法格式: public abstract void eat();
​ b:抽象类不一定有抽象方法,有抽象方法的类一定是抽象类
​ c:抽象类中可以有构造方法,抽象类不能进行实例化,那么要构造方法有什么作用呢?
​ 用于子类访问父类数据时的初始化
​ d:抽象类不能直接实例化那么,抽象类如何实例化呢?
​ 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
​ e:抽象类的子类
​ 要么是抽象类
​ 要么重写抽象类中的所有抽象方法

抽象类的成员特点
  • 抽象类的成员特点
    a:成员变量:既可以是变量,也可以是常量。
    b:构造方法:有。用于子类访问父类数据的初始化。
    c:成员方法:既可以是抽象的,也可以是非抽象的。

  • 抽象类的成员方法特性:
    a:抽象方法 强制要求子类做的事情。
    b:非抽象方法 子类继承的事情,提高代码复用性。

猫狗案例
public class MyTest {
    public static void main(String[] args) {
        //Animal animal = new Animal();
        Cat cat = new Cat();
        Dog dog = new Dog();
    }
}
//abstract 抽象的,可以修饰类,修饰方法。
abstract class Animal {
    //父类,他也不知道,子类对这个共性功能的具体实现,所以也没有必要给出共性功能的具体实现
    //抽象类,抽取所有子类的共性功能,但是不给出,共性功能的具体实现,而是交由子类根据自身的特性做以具体的实现。
    public abstract void eat();
    public abstract void sleep();
}
class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
    @Override
    public void sleep() {
        System.out.println("猫白天睡觉");
    }
}
class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
    @Override
    public void sleep() {
        System.out.println("狗晚上睡觉");
    }
}

接口

  • 接口概念:在java中接口是一个全部由抽象方法组成的集合,接口需要用interface定义,里面只有抽象方法和常量。

举例说明: 猫狗案例,我们想想狗一般就是看门,猫一般就是作为宠物了。

但是,现在有很多的驯养员或者是驯兽师,可以训练出:猫钻火圈,狗跳高,狗做计算等。而这些额外的动作,并不是所有猫或者狗一开始就具备的,这应该属于经过特殊的培训训练出来的。

所以,这些额外的动作定义到动物类中就不合适,也不适合直接定义到猫或者狗中,因为只有部分猫狗具备这些功能。
所以,为了体现事物功能的扩展性,Java中就提供了接口来定义这些额外功能,并不给出具体实现,将来哪些猫狗需要被培训,只需要这部分猫狗把这些额外功能实现即可

  • 接口特点:
    a:接口用关键字interface表示 格式: interface 接口名 {}
    b:类实现接口用implements表示 格式: class 类名 implements 接口名 {}
    c:接口不能实例化 ; 按照多态的方式来实例化。
    d:接口的子类
    a:可以是抽象类。但是意义不大。
    b:可以是具体类。要重写接口中的所有抽象方法。(推荐方案)

  • 接口成员变量特点:

成员变量:只能是常量,并且是静态的。
默认修饰符:public static final
建议:自己手动给出。
构造方法:接口没有构造方法。
成员方法:只能是抽象方法。
默认修饰符:public abstract
建议:自己手动给出。

案例说明
public class MyTest {
    public static void main(String[] args) {
        //接口的子类有两种选择:1.重写接口中的所有抽象方法,2.自己本身就是一个抽象类 但是意义不大。

        //接口中的成员特点:
        //1.接口中的成员变量,全部是公共的静态常量 前面存在默认修饰符  public static final
        System.out.println(A.NUM); //接口名直接调用
        //2.JDK1.7 之前接口中的方法,全部是抽象方法,不存在非抽象方法。方法的前面存在 默认修饰符 public abstract
        //3.接口中没有构造方法这一说。
        //4.接口不能直接new对象。
    }
}
interface A{
    public static final int NUM=100;
    public abstract void a();
    public abstract void aa();

     int sum(int a,int b);
}
 class B implements A{

     @Override
     public void a() {

     }

     @Override
     public void aa() {

     }

     @Override
     public int sum(int a, int b) {
         return 0;
     }
 }
  • 类与类,类与接口,接口与接口的关系:

a:类与类:继承关系,只能单继承,可以多层继承。
b:类与接口:实现关系,可以单实现,也可以多实现。并且还可以在继承一个类的同时实现多个接口。
c:接口与接口:继承关系,可以单继承,也可以多继承。

抽象类和接口的区别:

A:成员区别
抽象类:
成员变量:可以变量,也可以常量
构造方法:有
成员方法:可以抽象,也可以非抽象
接口:
成员变量:只可以常量
成员方法:只可以抽象
B:关系区别
类与类
继承,单继承
类与接口
实现,单实现,多实现
接口与接口
继承,单继承,多继承
C:设计理念区别
抽象类 被继承体现的是:”is a”的关系。 抽象类中定义的是该继承体系的共性功能。
接口 被实现体现的是:”like a”的关系。 接口中定义的是该继承体系的扩展功能。

注:jdk1.8后可以有静态方法和方法体。

案例说明

动物类:姓名,年龄,吃饭,睡觉。
动物培训接口:跳高
猫继承动物类
部分猫继承猫类并实现跳高接口

跳高接口通过抽象类测试基本功能。
通过接口测试扩展功能。

public abstract class Animal {
    String name;
    int age;
    public abstract void eat();
    public abstract void sleep();
}
public interface JumpInterface {
    void jump();
}
public class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("吃饭");
    }
    @Override
    public void sleep() {
        System.out.println("睡觉");
    }
}
public class 二哈 extends Dog implements JumpInterface{
    @Override
    public void eat() {
        System.out.println("二哈 吃狗粮");
    }

    @Override
    public void sleep() {
        System.out.println("二哈在家里睡觉");
    }

    public void sledding(){
        System.out.println("二哈 拉雪橇");
    }

    @Override
    public void jump() {
        System.out.println("二哈学会了跳高");
    }
}
public class MyTest {
    public static void main(String[] args) {
      
        二哈 eh = new 二哈();
        Dog dog = eh;
        dog.name = "二哈";
        dog.age = 2;
        dog.eat();
        dog.sleep();
        //向下转型。
        二哈 er = (二哈) dog;
        er.sledding();
        //er.jump();
        JumpInterface jumpInterface = eh;
        jumpInterface.jump();
        System.out.println(eh);
        System.out.println(er);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值