黑马程序员---面向对象一

时间:2022-08-27 08:54:23

面向对象一

----------- android培训java培训、java学习型技术博客、期待与您交流! ------------

1. 面向对象

1.1 概述

面向对象一种编程思想,是由面向过程发展而来。面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。

1.2 面向过程

强调的是功能行为,面向过程是一种以过程为中心的编程思想。面向过程他们不支持丰富的面向对象特性(比如继承、多态),就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。

1.3 面向对象的优点

1. 符合人们思考习惯,可以将复杂的事情简单化将程序员从执行者转换成了指挥者。

2. 信息隐藏,提高了程序的可维护性和安全性

3. 提高了程序的可重用性

1.4 面向对象的三大特征

面向对象具备如下3大特征:

1.封装(encapsulation)

2.继承(inheritance)

3.多态(polymorphism)

2.类与对象的关系

2.1 对象

2.1.1 什么是对象

概念:描述现实世界,就是描述事物的属性和行为。现实世界的每个事物都可以理解为对象。即万物皆对象。

2.1.2 对象的特点

    对象(object)代表现实世界中可以明确标识的一个实体。例如:一个学生、一张桌子、一间教室,一台电脑都可以看做是一个对象。即万物皆对象.

每个对象都有自己独特的属性和行为。

2.2 类

2.2.1 类的定义

    概念使用计算机语言就是不断的在描述现实生活中的事物。java中描述事物通过类的形式体现,类是具体事物的抽象,是概念上的定义。对象即是该类事物实实在在存在的个体。

类与对象的关系如图

黑马程序员---面向对象一

可以理解为:

类就是汽车的图纸

一辆汽车就是根据汽车生产的对象

2.2.2 类与对象

1.面向对象的java语言使用类对现实世界进行描述;

2.类是图纸,模板;

3.java的类就是现实世界的事物的映射.。

1) 成员变量-->(属性)

2) 成员方法--> (行为)

4.java中的对象就是依据类产生的实体。

5.总结

1)  java中先有类,后有对象。

2)  定义:java类就是定义类的成员即成员变量和成员方法。

2.3 成员变量与局部变量

2.3.1 局部变量

1) 方法中,参数列表中,语句中。

2) 必须给初始化值,没有初始值,不能使用

3) 在栈内存中

2.3.2 成员变量

1.属于类的成员,直接定义在类中;

2.有默认的初始化值;

1) 整数byteshortintlong =0

2) char='\uoooo'

3) boolean =flase

4) String =null;

5) 类类型 =null

6) 数组 =null

3.在堆内存中。

2.4 代码实例

项目名称

* 需求:使用java或.NET描述汽车车、修理工厂两个类,车具备名字、颜色、*数三个属性、车具备跑的行为,
              车在跑的时候应该判断是否够四个*,如果够四个*可以跑起,否则送去修车厂维修。
               修车厂具备,名字、地址、电话三个属性,具备修车的功能行为。*

Car类的代码

[java]  view plain copy 黑马程序员---面向对象一 黑马程序员---面向对象一
  1. /** 
  2.  * 汽车类的代码,有名字、颜色,车轮数等属性还有run()方法 
  3.  * */  
  4. public class Car {  
  5.     private String name;  
  6.     private String color;  
  7.     private int wheelNum;  
  8.     public String getName() {  
  9.         return name;  
  10.     }  
  11.     public void setName(String name) {  
  12.         this.name = name;  
  13.     }  
  14.     public String getColor() {  
  15.         return color;  
  16.     }  
  17.     public void setColor(String color) {  
  18.         this.color = color;  
  19.     }  
  20.     public int getWheelNum() {  
  21.         return wheelNum;  
  22.     }  
  23.     public void setWheelNum(int wheelNum) {  
  24.         this.wheelNum = wheelNum;  
  25.     }  
  26.     public Car(String name, String color, int wheelNum) {  
  27.         //super();  
  28.         this.name = name;  
  29.         this.color = color;  
  30.         this.wheelNum = wheelNum;  
  31.     }  
  32.     public void run(){  
  33.         System.out.println("一辆" + this.color +"色的,叫"this.name  +"的"this.wheelNum + "轮汽车正在行驶" );  
  34.           
  35.     }  
  36.     public Car(){}      
  37. }  
汽修厂的代码
[java]  view plain copy 黑马程序员---面向对象一 黑马程序员---面向对象一
  1. package com.ping.project;  
  2.   
  3. /** 
  4.  * 需求:汽车维修厂的类,有名字,有地址,有电话 
  5.  * */  
  6. public class CarRepair {  
  7.     private String name;  
  8.     private String address;  
  9.     private String phone;  
  10.     public String getName() {  
  11.         return name;  
  12.     }  
  13.     public void setName(String name) {  
  14.         this.name = name;  
  15.     }  
  16.     public String getAddress() {  
  17.         return address;  
  18.     }  
  19.     public void setAddress(String address) {  
  20.         this.address = address;  
  21.     }  
  22.     public String getPhone() {  
  23.         return phone;  
  24.     }  
  25.     public void setPhone(String phone) {  
  26.         this.phone = phone;  
  27.     }  
  28.     public CarRepair(String name, String address, String phone) {  
  29.         super();  
  30.         this.name = name;  
  31.         this.address = address;  
  32.         this.phone = phone;  
  33.     }  
  34.     public Car repairCar(Car car){  
  35.         if(car.getWheelNum() < 4){  
  36.             car.setWheelNum(4);  
  37.             System.out.println(car.getName()+ "已维修好!可以上路了");  
  38.         }  
  39.         return car;  
  40.     }  
  41.     public CarRepair(){}    
  42. }  
  43. //修车厂具备,名字、地址、电话三个属性,具备修车的功能行为  

主方法

public class CarTest {  
  
    /** 
     *  
     * 
     * 需求:使用java描述汽车车、修理工厂两个类,车具备名字、颜色、*数三个属性、车具备跑的行为, 
     *       车在跑的时候应该判断是否够四个*,如果够四个*可以跑起,否则送去修车厂维修。 
     *       修车厂具备,名字、地址、电话三个属性,具备修车的功能行为。* 
     * @param args 
     */  
    public static void main(String[] args) {  
        // TODO Auto-generated method stub  
        //新建4个汽车对象  
        Car car1 = new Car("小绵羊一号","红" ,4);  
        Car car2 = new Car("小绵羊二号","蓝" ,3);  
        Car car3 = new Car("小绵羊三号","黑" ,4);  
        Car car4 = new Car("小绵羊四号","白" ,4);  
        //新建一个汽车维修类  
        CarRepair cr = new CarRepair();  
        //一个对象数组,将所有的汽车类包含其中  
        Car [] cars ={car1 , car2 , car3, car4};  
        //循环输出汽车类的方法  
        for(int i = 0 ; i < cars.length ; i ++){  
            //判断若车轮小于4个则送汽车维修厂维修  
            if(cars[i].getWheelNum() < 4){  
                System.out.println(cars[i].getName() + "只有" + cars[i].getWheelNum() + "个*需要维修!");  
                cr.repairCar(cars[i]);   
            }  
            //调用汽车run()方法  
            cars[i].run();              
        }   
    }   
}  
[java] view plaincopy
输出:  
[java] view plaincopy
一辆红色的,叫小绵羊一号的4轮汽车正在行驶  
小绵羊二号只有3个*需要维修!  
小绵羊二号已维修好!可以上路了  
一辆蓝色的,叫小绵羊二号的4轮汽车正在行驶  
一辆黑色的,叫小绵羊三号的4轮汽车正在行驶  
一辆白色的,叫小绵羊四号的4轮汽车正在行驶

2.5 匿名对象

2.5.1 概念

   创建的对象都有名字,叫做非匿名对象。如果这个对象没有名字就叫做匿名对象。

2.5.2 匿名对象的简单演示

用上例的代码来举例

public class CarTest {
	/**
	 * 
	 * 
	 * 需求:使用java描述汽车车、修理工厂两个类,车具备名字、颜色、*数三个属性、车具备跑的行为,
	 * 车在跑的时候应该判断是否够四个*,如果够四个*可以跑起,否则送去修车厂维修。 修车厂具备,名字、地址、电话三个属性,具备修车的功能行为。*
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		// 新建一个汽车维修类
		CarRepair cr = new CarRepair();
		// 一个对象数组,将所有的汽车类包含其中
		Car[] cars = { new Car("小绵羊一号", "红", 4), new Car("小绵羊二号", "蓝", 3),
				new Car("小绵羊三号", "黑", 4), new Car("小绵羊四号", "白", 4) };
		// 循环输出汽车类的方法
		for (int i = 0; i < cars.length; i++) {
			// 判断若车轮小于4个则送汽车维修厂维修
			if (cars[i].getWheelNum() < 4) {
				System.out.println(cars[i].getName() + "只有"
						+ cars[i].getWheelNum() + "个*需要维修!");
				cr.repairCar(cars[i]);
			}
			// 调用汽车run()方法
			cars[i].run();
		}
	}
}
输出:
一辆红色的,叫小绵羊一号的4轮汽车正在行驶
小绵羊二号只有3个*需要维修!
小绵羊二号已维修好!可以上路了
一辆蓝色的,叫小绵羊二号的4轮汽车正在行驶
一辆黑色的,叫小绵羊三号的4轮汽车正在行驶
一辆白色的,叫小绵羊四号的4轮汽车正在行驶
输出效果一致!

3:内存结构图

1)  new Car().num=5;

2) new Car().clor="blue";

两个new 是两个不同的对象,在堆内存中有不同的空间,相互不相互干扰。

4:匿名对象的使用

1) 当执行一次方法时可以使用匿名对象。执行完毕后;该对象就变成了垃圾。

new Car().run();

2) 执行方法时,可以将匿名对象作为实际参数,传递进去。

3.封装

3.1 概念

   使对象的属性尽可能私有,对象的方法尽可能的公开。用private表示此成员属性为该类的私有属性。

   自己总结: 封装其实就是先将属性或方法用private访问修饰符定义后,再使用public方法获得其访问权。

注:(如果不指明谁调用方法,则默认为this,区分实例变量和局部变量时一定要写this)。

3.2 封装的好处

1.隐藏了类的具体实现;

2.提高对象数据的安全性;

3.提高了程序的可维护性和安全性。

3.3 代码实例

要求:新建一个person类,类中有属性name,age,sex和一个sayHi()方法对其属性进行封装处理,在main()方法中赋值,并打印到sayHi()

public class TestPrivate {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Person p1 = new Person();
		// 由下面代码可知访问Person的各个属性必须要通过其属性相应的方法
		p1.setAge(18);
		p1.setName("胡志平");
		p1.getName();
		p1.getAge();
		p1.setSex("男");
		p1.sayHi();
	}
}
class Person {
	// 封装后的name属性
	private String name;
	// 封装后的age属性
	private int age;
	private String sex;

	// 得到sex的值
	public String getSex() {
		return sex;
	}

	// 设置sex的值
	public void setSex(String sex) {
		// 在方法内设置筛选条件,以防错误数据录入
		if (sex.equals("男") || sex.equals("女"))
			this.sex = sex;
		else
			System.out.println("性别只能填“男”与“女”");
	}
	// 得到Name的值的方法
	public String getName() {
		return name;
	}
	// 设置Name的值的方法
	public void setName(String name) {
		this.name = name;
	}
	// 得到age的值
	public int getAge() {
		return age;
	}
	// 设置age的值
	public void setAge(int age) {
		if (age < 0 || age > 1000)
			System.out.println("请输入正确年龄");
		else
			this.age = age;
	}
	public void sayHi() {
		System.out.println("我的名字是:" + name + ",性别是:" + sex + ",今年:" + age
				+ "岁。");
	}
}
输出:
我的名字是:胡志平,性别是:男,今年:18岁。

4.构造函数

Java中通过构造函数确保对象的初始化,这是一个对象被创建时会被调用的特殊方法.Java中通过构造方法,可以保证类的每个对象都可以初始化

4.1 构造函数示例

class Person {
	String name;
	int age;
	// 构造函数
	Person(String n, int a) {
		name = n;
		age = a;
	}	
	//普通成员函数
	void speak() {
		System.out.println("hah");
	}
}

4.2 构造函数的特点

1.函数名与类名相同;

2.不需要定义返回值和void 不同;  

3.不可以定义return语句。

4.3 构造函数作用

1.用于给对象初始化

4.4 默认无参会构造函数

1.之前并没有定义构造函数,系统提供默认无参构造。

2.但如果用户自定义构造函数,则系统不再提供无参会构造方法。

4.5 构造函数的重载

1.函数有重载,构造函数是函数,那么也具备重载的特性;

2.多个构造函数以重载的形式体现

代码实例:

class Person {
String name;
int age;
//无参数构造函数
Person() {
System.out.println("这是无参的构造函数");
}
//有参数构造函数
Person(int a) {
age = a;
System.out.println("有参构造1");
}
//有参数构造函数
Person(String n) {
name = n;
System.out.println("有参构造2");
}
//有参数构造函数
Person(int a, String n) {
age = a;
name = n;
System.out.println("有参构造");
}
//普通函数
void speak() {
System.out.println("hah");
}
}

4.6 构造函数和普通函数的区别

1.写法不同,构造函数没有返回值和静态

2.运行

1) 构造函数,用于对象初始化。对象一建立就运行。

2) 普通函数,对象调用后才执行,是对象具备的功能。

3) 对象建立构造函数只运行一次,普通函数可以运行多次。

4.7 构造代码块

1. 格式示例{}

class Person {
String name;
int age;
// 构造代码块,给所有对象进行初始化。
{
System.out.println("这是构造代码块");
}
// 无参数构造函数
Person() {
System.out.println("这是无参的构造函数");
}
// 有参数构造函数
Person(int a, String n) {
age = a;
name = n;
System.out.println("有参构造");
}
// 普通函数
void speak() {
System.out.println("名字:"+name+" 姓名:"+age+"hah");
}
}

2.作用

1) 给对象进行初始化。对象一建立就运行并且优先于构造函数。

2.与构造函数区别

1) 构造代码块和构造函数的区别,构造代码块是给所有对象进行统一初始化, 构造函数给对应的对象初始化。

2) 构造代码块的作用:把不同对象的共性内容,放到构造代码块中,统一初始化。

class Person{
String name;
int age;
     // 构造代码块,给所有对象进行初始化。
{
System.out.println("我是构造代码块");
} 
Person() {
System.out.println("无参构造");
}
Person(String n, int a, String g) {
name = n;
age = a;
    System.out.println("有参构造");
}
void run() {
System.out.println("我在跑。。。。");
}
}
class Demo9 {
public static void main(String[] args) {
System.out.println();
Person p1 = new Person();
Person p2 = new Person("jack", 1, "男");
}
}

5.this关键字

5.1 this的意义

this代表所在函数所属对象的引用。因为函数需要被调用才会执行,当前的对象调用了它,所以this就代表所在函数所属对象的引用

5.2 代码实例

需求需要构造函数间的调用

1.定义Person

1) 有姓名年龄成员变量,有说话的方法。

2) 定义构造方法,无参的,多个有参的。

class Person {
String name;
int age;
//无参数构造函数
Person() {
System.out.println("这是无参的构造函数");
}
//有参数构造函数
Person(int a) {
age = a;
System.out.println("有参构造1");
}
//有参数构造函数
Person(String n) {
name = n;
System.out.println("有参构造2");
}
//有参数构造函数
Person(int a, String n) {
age = a;
name = n;
System.out.println("有参构造");
}
//普通函数
void speak() {
System.out.println("你好!");
}
}

2.属性值还没有什么问题,但假设定义40个成员变量,第一个有参构造初始化20个变量,第二个有参构造初始化40个变量,这为属性赋值就显得非常麻烦了。

1) 第二个有参构造想要调用第一个有参构造。通过this关键字就可以解决该问题。

class Student {
String name;
String gender;
int age;
Student() {}
Student(String name) {
this();
this.name = name;
}
Student(String name, String gender, int age) {
this(name);
System.out.println(this); // Student@c17164
this.gender = gender;
this.age = age;
}
void speak() {
run();
System.out.println("姓名:" + name + " 性别:" + gender + " 年龄:" + age
);
}
void run() {
System.out.println("我在跑。。。。");
}
}
class Demo2 {
public static void main(String[] args) {
Student p = new Student("jack", "男", 20);
System.out.println(p); // Student@c17164
Student p2 = new Student("rose", "女", 18);
System.out.println(p2);
p.speak();
}
}

注意:

1) this只能在非静态中(没有static修饰的)函数使用

2) 构造函数间相互调用必须放在构造函数的第一行,否则编译错误

3) 可以解决构造函数中对象属性和函数形参的同名问题。

6.static 关键字

6.1 static作用

为了实现对象之间重复属性的数据共享。

6.2 代码实例

1.定义Count类

1) 里面有一个静态修饰的成员变量;

2) 一个方法,调用一次成员变量减一。

public class SimpleDemo {
	public static void main(String args[]) {
		new Count().listCount();
		new Count().listCount();
	}
}
class Count {
	int count = 3;

	public void listCount() {
		System.out.println("还有" + --count + "个数字!");
	}
}
class Count{
int count = 3 ;
public void listCount(){
System.out.println("还有" + --count + "个数字!");
}
输出:
还有2个数字!
还有2个数字!
而如果count是静态的呢?

public class StaticDemo {
	public static void main(String args[]) {
		new Count().listCount();
		new Count().listCount();
	}
}
class Count {
	static int count = 3;

	public void listCount() {
		System.out.println("还有" + --count + "个数字!");
	}
}
输出:
还有2个数字!
还有1个数字!

 3)创建Count对象

1:分析内存

总结:每个对象都共用着相同的count的变量,staitc修改的变量随着类的产生而产生,static只会与相应的类同存。

6.3 static修饰类的成员

6.3.1 static修饰成员变量

1.非静态成员变量,需要创建对象来访问;

2.静态成员变量:使用类名直接调用,也可以通过对象访问。

6.3.2 static修饰成员方法

1.静态函数:使用类名直接调用,也可以通过对象访问

1)静态函数的特点:

[1] 静态函数中不能访问非静态成员变量,只能访问静态变量。

[2] 静态方法不可以定义this,super关键字.

[3] 因为静态优先于对象存在.静态方法中更不可以出现this

2.非静态函数:非静态函数中可以访问静态成员变量

class Person {
String name;
int age;
String sex;
//static 修饰成员变量
static String country = "中国";
Person()
    {
}
Person(String name, int age, String sex) 
    {
this.name = name;
this.age = age;
this.sex= sex;
}
void speak() {             //非静态方法
//非静态方法可以访问静态成员
System.out.println("国籍:" + country );
System.out.println("国籍:" + country + " 姓名:" + name + " 性别:" + sex + " 年龄:" + age + " !");
}
static void run()          //静态方法
    {
    System.out.println("国籍:"+country); //静态方法只能访问静态成员变量。
    System.out.println("姓名:" +name); //静态方法访问非静态成员变量,编译报错。
this.speak();//静态方法中不可以出现this,编译报错
}
}
注意:

1:静态函数中不能使用非静态变量

2:非静态函数可以访问静态变量

6.3.3 静态函数的特点

静态函数不能访问非静态成员变量    

6.3.4 静态成员变量的特点

1.静态成员变量可以直接被类名调用;

2.静态成员变量被所有实例(对象)所共享;

3.静态成员变量随着类的加载而加载,随着类的消失而消失。所以它的生命周期要比普通对象的实例变量长;

4.静态成员变量优先于对象存在;

静态成员是先存在,对象是后存在(对象需要创建)

6.3.5 静态变量(类变量)和实例变量的区别

1.存放位置

  1) 类变量随着类的加载而加载存在于方法区中

  2)实例变量随着对象的建立而存在于堆内存中

2.生命周期

  1)类变量生命周期最长,随着类的消失而消失

  2)实例变量生命周期随着对象的消失而消失

6.4 静态的优缺点

1.优点:对象的共享数据进行单独空间的存储,节省空间 例如Person 都有国籍。该数据可以共享并且可以通过类名直接调用.

2.缺点:静态成员变量的生命周期过长,同时静态方法的访问出现局限性。(静态方法只能访问静态成员变量)

6.5 静态代码块

1:静态代码块

static

{

静态代码块执行语句;

}

2:静态代码块特点

随着类的加载而加载。只执行一次,优先于主函数。用于给类进行初始化。

public class PersonDemo {
	public static void main(String[] args) {
		// 访问静态成员
		// 直接通过类名来调用
		String country = Person.country;
		System.out.println(country);
		// 通过对象.成员的形式访问
		Person p1 = new Person("john", 20, "男");
		p1.country = "美国";
		p1.speak();
	}
}
class Person {
	String name;
	int age;
	String gender;
	// static 修饰成员变量
	static String country = "中国";
	static {
		System.out.println("这是静态代码块");
	}
	{
		System.out.println("这是构造代码块");
	}

	Person() {
		System.out.println("无参数构造");
	}

	Person(String name, int age, String gender) {
		this.name = name;
		this.age = age;
		this.gender = gender;
		System.out.println("有参数构造");
	}
	// 非静态方法
	void speak() {
		// 非静态方法可以访问静态成员
		System.out.println("国籍:" + country);
		System.out.println("国籍:" + country + " 姓名:" + name + " 性别:" + gender
				+ " 年龄:" + age + " !");
		// 非静态方法可以调用静态方法
		run();
	}
	// 静态方法
	static void run() {
		// 静态方法只能访问静态成员变量。
		System.out.println("国籍:" + country);
	}
}
输出:
这是静态代码块
中国
这是构造代码块
有参数构造
国籍:美国
国籍:美国 姓名:john 性别:男 年龄:20 !
国籍:美国

6.4 main方法

6.4.1 格式

public static void main(String[] args){     

}

6.4.2 概念

主函数是什么:主函数是一个特殊的函数,作为程序的入口,可以被jvm识别。

6.4.3 参数说明

主函数的参数说明:

       public :代表该函数的访问权限是最大的。

       static :代表主函数随着类的加载,就已经存在了。

       void:  主函数没有具体的返回值

       main : 不是关键字,是一个特殊的单词可以被jvm识别。

       (String[] args) 函数的参数,参数类型是一个数组,该数组中的元素是字符串。字符串类型的数组。

       主函数的格式是固定的:jvm能够识别

       jvm在调用函数是,传入的是new String[0];

可以在dos窗口中执行 java  Demo5   hello  world   给类Demo5main方法传递2个参数,参数与参数之间通过空格隔开。

class Demo5 
{
public static void main(String[] args) 
{
// 获取String[] args 数组长度
System.out.println(args.length);
// 变量args数组
for (int x = 0; x < args.length; x++) {
System.out.println(args[x]);}
}
}
class MainTest 
{
public static void main(String[] args) 
{
// 字符串数组
String[] arr = { "good", "study", "java" };
// 调用Demo5类的main方法,传递参数。
Demo5.main(arr);
}
}

----------- android培训java培训、java学习型技术博客期待与您交流! ------------