01

    科技2022-07-16  104

    Java面向对象编程

    java面向对象学习的三条主线:

    Java类和类的成员:属性Field、方法Method、构造器Constractor;代码块、内部类面向对象三大特征:封装性、继承性、多态性、(抽象性)其他关键字:this、super、static、final、abstract、interface、package、import等

    面向对象OOP与面向过程POP对比:

    面向过程:强调的是功能行为,以函数为最小单位,考虑怎么做。

    ①打开冰箱

    ②抬起大象,放进冰箱

    ③关上冰箱门

    面向对象:强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。

    人{

    ​ 打开(冰箱){

    ​ 冰箱.打开();

    ​ }

    ​ 抬起(大象){

    ​ 大象.进入(冰箱);

    ​ }

    ​ 关闭(冰箱){}

    }

    冰箱{

    ​ 打开(){}

    ​ 关闭(){}

    }

    大象{

    ​ 进入(冰箱){}

    }

    1 类和对象

    类是对一类事务的描述,是抽象的、概念上的定义

    对象是实际的该类事务的每个个体,因此也成为实例(instance)

    面向对象设计的重点是类的设计。

    类的设计就是类的成员的设计。

    属性(field):对应类中的成员变量、域、字段行为:对应类中的成员方法(method)、函数

    ①类和对象的使用

    创建类,设计类的成员创建类的对象通过“对象.属性”或“对象.方法”调用对象的结构

    如果创建了一个类的多个对象,则每个对象都独立的拥有一套类的属性(非static的);意味着,如果我们修改一个对象的属性a,则不影响另外一个对象属性a的值。

    对象内存解析

    堆(Heap):存放对象实体栈(Stack):存储局部变量(方法中的变量都是局部变量)方法区(Method Area):类信息、常量、静态变量、即时编译器编译后的代码

    ②匿名对象

    对于不定义对象的句柄,直接调用这个对象的方法。这样的对象就叫做匿名对象。

    比如:System.out.println(new Person().shout()) 直接输出新new的对象的方法

    ​ System.out.println((new Person().name)) 直接输出新new的对象的属性(默认name=null,也可以使用带有参数的构造器进行赋值:System.out.println(new Person(“jiwei”, 24)))也可以输出属性。

    ③类中属性的使用:

    属性(成员变量) VS 局部变量

    相同点:

    1 定义变量的格式:数据类型 变量名 = 变量值2 先声明,后使用3 变量都有其作用域

    不同点:

    1 在类中声明的位置不同

    属性:直接定义在类的一对{}内

    局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量

    2 关于权限修饰符的不同

    属性:可以在声明属性的时候,指明其权限,使用public、private、缺省、protected等权限修饰符

    局部变量:不可以使用权限修饰符

    3 默认初始化值的情况

    属性:根据其类型都有默认初始化值:整型(byte short int long)0、浮点型(float double)0.0、字符型(char)0、引用数据类型(类 数组 接口)null

    局部变量:没有默认初始化值,意味着调用局部变量时一定显示赋值,形参在调用时赋值即可。

    4 在内存中加载的位置不同

    属性:加载的到堆空间(非static)

    局部变量:加载到栈空间

    成员变量(属性)和局部变量的内存解析:

    对象属性的默认初始化值:

    ④类中方法的使用:

    方法描述类应该有的功能。

    分类:

    无返回值有返回值无形参void 方法名(){}返回值类型 方法名(){}有形参void 方法名(形参列表){}返回值类型 方法名(形参列表){}

    方法的声明:权限修饰符 返回值类型 方法名(形参列表){

    ​ 方法体}

    关于权限修饰符:private 、public 、缺省、 protected

    关于返回值类型:有返回值的、没返回值的

    有返回值的:需要return关键字返回指定类型的变量或常量,一定需要返回

    无返回值的:声明时需要使用void来表示,如果用“return”是结束方法的作用

    方法名:属于标识符,见名知意

    形参列表:方法可以声明0个,1个或多个形参。

    return关键字的使用:

    方法的使用:可以调用当前类的属性或方法;方法中不可以定义其他的方法

    上述案例的代码

    package com.atguigu.test; /** * @author:Ven * @date:2020/7/20 - 14:14 * @function: */ public class StudentTest01{ public static void main(String[] args) { //声明student类型的数组 Student01[] students = new Student01[20]; for (int i = 0; i < students.length; i++) { //给数组元素赋值 students[i] = new Student01(); //学号1-20 students[i].number = (i+1); //年级:1-6 students[i].state = (int) (Math.random()*(6-1+1)+1); //成绩:0-100 students[i].score = (int) (Math.random()*(100-0+1)); } //遍历学生数组 StudentTest01 test01 = new StudentTest01(); test01.printStuInfo(students); System.out.println("********************************"); //问题1 打印出3年级学生的信息 test01.searchState(students, 3); System.out.println("********************************"); //问题2 使用冒泡排序按学生成绩排序,并遍历所有学生信息 test01.sortStuInfo(students); //遍历学生信息 test01.printStuInfo(students); } //遍历学生数组 public void printStuInfo(Student01[] student01s){ //遍历学生信息 for (int i = 0; i < student01s.length; i++) { System.out.println(student01s[i].number+"\t"+student01s[i].score+"\t"+student01s[i].state); } } //打印出3年级学生的信息方法 public void searchState(Student01[] student01s, int state){ for (int i = 0; i < student01s.length; i++) { if (student01s[i].state==state){ System.out.println(student01s[i].number+"\t"+student01s[i].score); } } } //使用冒泡排序按学生成绩排序,并遍历所有学生信息 public void sortStuInfo(Student01[] student01){ for (int i = 0; i < student01.length-1; i++) { for (int j = 0; j < student01.length - 1 - i; j++) { if (student01[j].score>student01[j+1].score){ Student01 temp = student01[j]; student01[j] = student01[j+1]; student01[j+1] = temp; } } } } } class Student01{ int number;//学号 int state;//年级 int score;//成绩 }

    上述案例的内存解析

    编译完源代码以后,生成一个或多个字节码文件。

    我们使用JVM中的类的加载器和解释器对生成的字节码文件进行解释运行。意味着,需要将字节码文件对应的类加载到内存中,涉及到内存解析。

    虚拟机栈,即为平时提到的栈结构,我们将局部变量存储到栈结构中。

    堆,new出来的结构(比如数组、对象)。对象的属性(非static)

    内存解析案例:

    ⑤方法的重载

    定义:在同一个类中,允许存在一个以上的同名方法,只要他们的参数个数或者参数类型不同即可

    ​ “两同一不同”:同一个类、同一个方法名,参数列表不同(参数个数、参数类型)

    public class OverLoadTest { public static void main(String[] args) { OverLoadTest test = new OverLoadTest(); test.getSum(1,2); } //如下的4个方法构成了重载 public void getSum(int i,int j){System.out.println("1");} public void getSum(double d1,double d2){System.out.println("2");} public void getSum(String s ,int i){System.out.println("3");} public void getSum(int i,String s){System.out.println("4");} //如下的3个方法不能与上述4个方法构成重载 // public int getSum(int i,int j){return 0;} // public void getSum(int m,int n){} // private void getSum(int i,int j){} }

    ⑤可变个数形参

    jdk5.0新增特性,允许直接定义能和多个实参相匹配的形参。通常用在与数据库交互的时候!

    具体使用:

    格式:方法名(参数的类型名 …参数名)

    当调用可变个数参数的方法时,参数个数可以是0个、1个。。。

    可变个数形参的方法与本类方法中方法名相同,形参个数不同的方法之间构成重载

    可变个数形参的方法与本类中方法名相同,形参类型也相同的数组,不能共存。

    可变个数形参必须声明在末尾!并且也只能存在一个可变个数形参。

    public void show (int i , String … strs)

    public class MethodArgsTest { public static void main(String[] args) { MethodArgsTest test = new MethodArgsTest(); test.show(19); test.show("jiWei"); test.show("jiWei", "sunYan", "liuZiXin"); } public void show(int i){ System.out.println(i); } public void show(String s){ System.out.println(s); } public void show(String...s){ System.out.println(s); for (int i = 0; i < s.length; i++) { System.out.println(s[i]); } } }

    ⑥方法参数的值传递机制

    关于变量的赋值

    如果变量是基本数据类型,此时赋值的是变量所保存的数据值如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值

    关于方法的形参的传递机制:值传递

    形参:方法定义时,声明的小括号内的参数实参:方法调用时,实际传递给形参的数据

    值传递机制的内存解析

    案例1:

    案例2:

    案例3(!!!!)

    案例4(!!!!)

    案例5(!!!!)

    案例6(!!!)

    ⑦递归方法的使用(了解)

    需要从内存中方法的入栈出栈进行分析!!

    2 OOP特征:封装性

    ①思想

    把该隐藏的隐藏起来,把该暴露的暴露出来。

    具体表现为信息的隐藏:

    通过将数据声明为私有的private,再提供公共的public方法:**getXxx()和setXxx()**实现对属性的操作。 class Animal { private int legs;// 将属性legs定义为private,只能被Animal类内部访问 public void setLegs(int i) { // 在这里定义方法 eat() 和 move() if (i != 0 && i != 2 && i != 4) { System.out.println("Wrong number of legs!"); return; } legs = i; } public int getLegs() { return legs; } } public class Zoo { public static void main(String args[]) { Animal xb = new Animal(); xb.setLegs(4); // xb.setLegs(-1000); //xb.legs = -1000; // 非法 System.out.println(xb.getLegs()); } }

    ②权限修饰符

    3构造器

    ①概念

    构造器或者成为构造方法

    构造器又分为了无参构造器和有参构造器。

    系统默认提供一个隐式的无参构造器;也可以自己显式定义多个构造器(有参或无参)

    特点:

    具有和类相同的名称

    不声明返回值:public Person(){}

    修饰符有:不能被static、final、synchronized、abstract、native修饰,不能有return语句返回值。

    ②作用

    创建对象;给对象进行初始化!

    比如:Order o = new Order(); Person p = new Person(“Peter”,15);

    我的理解就是,就是初始化不同类型的对象,有的对象初始有属性,有的初始没有属性。

    ③代码

    案例1:

    public class Animal { private int legs; //无参构造器 public Animal(){ //构造器内初始化属性,也就是说初始化对象的时候,默认animal就有4个legs legs = 4; } public void setLegs(int i){ legs = i; } public int getLegs(){ return legs; } } public class AnimalTest { public static void main(String[] args) { Animal animal = new Animal(); System.out.println(animal.getLegs());//4 } }

    案例2:

    public class PersonTest { public static void main(String[] args) { Person person = new Person(); System.out.println(person.getAge());//因为在构造器内初始化了age=18 person.setAge(29);//使用setAge重新设置age = 29 System.out.println(person.getAge()); System.out.println(person.getName());//string类型默认值为null person.setName("jiwei"); System.out.println(person.getName()); } } public class Person { //私有属性 private String name; private int age; //无参构造器,设置age默认值为18 public Person(){ age = 18; } public void setName(String name){ this.name = name; } public String getName(){ return name; } public void setAge(int age){ this.age = age; } public int getAge (){ return age; } }

    案例3:有参构造器和无参构造器对比:

    //测试类 public class TriAngleTest { public static void main(String[] args) { //使用无参构造器实例化一个三角形 TriAngle angle = new TriAngle(); angle.setBase(5.0); angle.setHeight(10.0); System.out.println(angle.findArea()); System.out.println("=============="); //使用有参构造器实例化一个三角形 TriAngle angle1 = new TriAngle(6.0, 3.0); System.out.println(angle1.findArea());}} //三角形类 public class TriAngle { private double base;//底 private double height;//高 //无参构造器 public TriAngle(){} //有参构造器 public TriAngle(double base, double height){ this.base = base; this.height = height;} //get、set方法 public double getBase() { return base;} public void setBase(double base) { this.base = base; } public double getHeight() { return height;} public void setHeight(double height) { this.height = height; } /** * @Author jiwei * @Description //TODO 计算三角形面积 * @return 三角形的面积 **/ public double findArea(){ return height*base*0.5;}}

    ④构造器重载

    举例:

    public class Person { private String name; private int age; private Date birthDate; public Person(String n, int a, Date d) { name = n; age = a; birthDate = d; } public Person(String n, int a) { name = n; age = a; } public Person(String n, Date d) { name = n; birthDate = d; } public Person(String n) { name = n; age = 30; } }

    ⑤JavaBean

    JavaBean指符合如下标准的Java类:

    类是公共的有一个无参的公共的构造器有属性,且有对应的get、set方法

    JavaBean示例:

    public class JavaBean { private String name; // 属性一般定义为private private int age; public JavaBean() { } public int getAge() { return age; } public void setAge(int a) { age = a; } public String getName() { return name; } public void setName(String n) { name = n; } }

    ⑥UML类图

    4关键字

    ①this关键字

    它在方法内部使用,即这个方法所属对象的引用;

    它在构造器内部使用,表示该构造器正在初始化的对象

    this 可以调用类的属性、方法和构造器

    ②package关键字

    package语句作为Java源文件的第一条语句,指明该文件中定义的类所在

    的包。(若缺省该语句,则指定为无名包)。它的格式为:

    package 顶层包名**.**子包名 ;

    举例:

    pack1\pack2\PackageTest.java package pack1.pack2; //指定类PackageTest属于包pack1.pack2 public class PackageTest{ public void display(){ System.out.println("in method display()"); } }

    包对应于文件系统的目录,package语句中,用 “.” 来指明包(目录)的层次;

    包通常用小写单词标识。通常使用所在公司域名的倒置:com.atguigu.xxx

    ③import关键字

    import语句告诉编译器到哪里去寻找类。

    语法格式:

    import 包名**.** 类名**;**

    5MVC设计模式

    Processed: 0.010, SQL: 8