对象和封装

  • Post author:
  • Post category:其他


类是面向对象中的一个很重要的概念,因为类是很多个具有相同属性和行为特征的对象所抽象出来的,对象是类的一个实例。

类具有三个特性:封装、继承和多态。



三大特征:

  • 封装:核心思想就是“隐藏细节”、“数据安全”,将对象不需要让外界访问的成员变量和方法私有化,只提供符合开发者意愿的公有方法来访问这些数据和逻辑,保证了数据的安全和程序的稳定。所有的内容对外部不可见。

  • 继承:子类可以继承父类的属性和方法,并对其进行拓展。将其他的功能继承下来继续发展 。

  • 多态:同一种类型的对象执行同一个方法时可以表现出不同的行为特征。通过继承的上下转型、接口的回调以及方法的重写和重载可以实现多态。方法的重载本身就是一个多态性的体现。



三大思想:

面向对象思想从概念上讲分为以下三种:OOA、OOD、OOP

  • ​ OOA:面向对象分析(Object Oriented Analysis)
  • ​ OOD:面向对象设计(Object Oriented Design)
  • ​ OOP:面向对象程序(Object Oriented Programming )



类与对象:

(1)类是一类事务,是根据一般性抽象出来的;例如:人;动物.

  • 类由属性和方法组成:

    • 属性:就相当于人的一个个的特征

    • 方法:就相当于人的一个个的行为,例如:说话、吃饭、唱歌、睡觉

类名称 对象名称 = new 类名称() ;

  • 访问类中的属性或方法(方法的定义),则可以依靠以下的语法形式:

    • 访问类中的属性: 对象.属性 ;
    • 调用类中的方法: 对象.方法(实际参数列表) ;

      • 类必须编写在.java文件中;
      • 一个.java文件中,可以存在N个类,但是只能存在一个public修饰的类;
      • .java文件的文件名必须与public修饰的类名完全一直;
      • 同一个包中不能有重名的类;

(2)对象,是类的一个特例、实例。例如:小轿车、卡车、公共汽车等。对象通过new关键字,完成实例化(例如: Student stu = new Student() ; 。

(3)new关键字,其实本质就是申请分配内存,使Student类中的变量、方法都对应分配的内存单元。



面向过程和面向对象的区别:

面向过程 面向对象
区别 事物比较简单,可以用线性的思维去解决 事物比较负载,使用简单的线性思维无法解决
共同点 使用面向对象的思维 使用,面向过程来处理
优点: 性能高,流程和步骤清晰,容易理解 易扩展、代码复用率高、利于后期扩展和维护,提升开发效率
不足: 复用率低,扩展性差,维护难度高 一定程度上增加系统开销



面向对象程序设计的基本步骤:

  1. 发现类
  2. 发现类的属性
  3. 发现类的方法



类图:

类图以反映类的结构(属性,操作)及类之间的关系为主要目的,描述软件系统的结构,是一种静态建模的方法

类图包含如下三个组成部分:

  1. 定义的类名,如AppTree,Corn
  2. 类中属性,如AppleTree类中的name,brand等
  3. 类中方法,如print()方法

注意:”+“表示public ,”-“表示private,”#”表示protected



小结:

设计类是需要遵循的原则如下:

  1. 属性和方法是为了解决业务问题设置
  2. 关注主要属性和方法
  3. 如果没有必要,就不要增加额外的类,属性和方法



匿名对象:

  • 没有对象名称的对象就是匿名对象。 即栈内存中没有名字,而堆内存中有对象。
  • 匿名对象只能使用一次,因为没有任何的对象引用,所以将称为垃圾,等待被GC回收。
  • 只使用一次的对象可以通过匿名对象的方式完成,这一点在以后的开发中将经常使用到。
public static void main(String[] args){
	//Math2 m=new Math2();
	//int num=m.sum(100,200);
	//不通过创建对象名,直接实例对象调用,这就是匿名对象。因为没有对象名指向对象,所以只能调用一次,然后被GC回收。
	int num = new Math().sum(100,200);
	System.out.println(num);
}
class Math2{
	int sum(int x,int y){
		return x+y;
	}
}



构造方法(构造器)

  1. 构造方法的作用?

    ​ 用于对象初始化

  2. 语法:Person p = new Person();

    ​ 在右侧Person后面出现的小括号, 其实就是在调用构造方法



    语法:

    [访问修饰符]方法名([参数列表]){

    ​ //…省略方法体的代码

    }

  3. 执行时机:

    ​ 在创建对象时,自动调用

  4. 特点

    • 所有的Java类中都会至少存在一个构造方法

    • 如果一个类中没有明确的编写构造方法, 则编译器会自动生成一个无参的构造方法, 构造方法中没有任何的代码!

    • 如果自行编写了任意一个构造器, 则编译器不会再自动生成无参的构造方法。



    无参构造方法和有参构造方法:

    1. 无参构造方法: 生成初始化对象,属性都是默认值,系统默认提供
    2. 有参构造方法:生成初始化对象,属性都是实参提供,当你显示声明了有参构造方法
  5. 定义格式

    • 与普通方法基本相同, 区别在于: 方法名称必须与类名相同, 没有返回值类型的声明 ;

    • 建议自定义无参构造方法,不要对编译器形成依赖,避免错误发生。

    • 当类中有非常量成员变量时,建议提供两个版本的构造方法,一个是无参构造方法,一个是全属性做参数的构造方法。

    • 当类中所有成员变量都是常量或者没有成员变量时,建议不提供任何版本的构造。

/*
苹果树种类
  */

public class AppleTree {
    public String name="苹果树"; //名称
    public String brand;//品种
    public int growTime=10; //生长期
    public int harvesTime=2; //采摘期
    public  int numsOfFruits=100; //果实数量
    public  String status="生长期"; //生长状态
    public boolean isHarvested=false; //是否已采摘


    /*
    * 类的无参构造方法
    * */
    public  AppleTree(){
        this.brand="金帅";
    }

    public  void print(){
        System.out.println("*****作物特性******");
        System.out.println("您种植了"+this.name+"天");
        System.out.println("生长期"+this.growTime+"天+采摘期"+this.harvesTime+"天+果实数量为"+this.numsOfFruits+"+现在处于"+this.status);
        System.out.println(this.name+"属于水果物种,品种"+this.brand);

    }

    public static void main(String[] args) {
        AppleTree appleTree=new AppleTree();
        appleTree.print();
    }

}

这里,AppleTree()方法就是类的无参构造方法

当执行 AppleTree appleTree=new AppleTree(); 就会执行自定义构造方法



重载(Overload)



方法的重载

  • 方法名相同

  • 参数类型和个数不同

  • 修饰符和返回值类型不同

  • 方法的重载与返回值无关;

  • 方法的重载 ,可以让我们在不同的需求下, 通过传递不同的参数调用方法来完成具体的功能。

    当你显示声明了有参构造方法,系统不提供无参构造方法,此时可以自定义一个无参构造方法

    类的成员方法和构造方法都可以进行重载

int sum(int x, int y){
	int z = x + y;
	return z;
}
double sum(double x, double y){
	double z = x + y;
	return z;
}



构造方法的重载

  • 一个类, 可以存在多个构造方法 ;
  • 参数列表的长度或类型不同即可完成构造方法的重载 ;
  • 构造方法的重载 ,可以让我们在不同的创建对象的需求下, 调用不同的方法来完成对象的初始化 ;



重写(Override):

  • 参数列表必须完全与被重写的方法相同;
  • 返回类型必须完全与被重写的返回类型相同;
  • 访问权限不能比父类被重写的方法的访问权限更低。例如父类方法为public,子类就不能为protected;
  • 父类的成员方法只能被它的子类继承;
  • 声明为static和private的方法不能被重写,但是能够被再次声明
public class Demo{
    public static void main(String[] args){
        Student student=new Student();
        student.say();
    }
}
class Person{
    public void say(){
        System.out.println("锄禾日当午,汗滴禾下土。");
    }
}
class Student extends Person{
    public void say(){
        System.out.println("锄禾日当午,玻璃好上霜。要不及时擦,整不好得脏。");
    }
}
//结果为:
//锄禾日当午,玻璃好上霜。要不及时擦,整不好得脏。



重写与重载的区别

  1. 方法重写设涉及的是子类和父类之间的同名方法,要求方法名相同,参数列表不同,与返回值类型和访问修饰符无关
  2. 方法重载涉及同一个类中的同名方法,要求方法名相同,参数列表不同,与返回值类型和访问修饰符无关



关键字:



this:

img

  • 调用类中的属性
  • 调用类中的方法或构造方法 ,注意:在一个构造方法中,调用另一个构造方法时,调用的代码必须编写在构造方法的第一行。
  • 表示当前对象
  • 调用成员变量,方法
  • 调用已定义的构造方法

因为this关键字是在对象内部指代自身的引用,所以它只能调用实例变量,实例方法和构造方法,不能调用类变量和方法,也不能调用局部变量



this关键字主要有三种应用场景
  1. 使用this关键字调用成员变量,解决成员变量和局部变量的同名冲突

     public  AppleTree(String brand){
            this.brand=brand; //成员变量和局部变量同名,必须使用this关键字
        }
    
  2. 使用关键字this调用成员方法

     public  void changeName(String name){
            this.name=name; 
         	this.print():
        }
    
  3. 使用this关键字调用已定义的构造方法

class Person{
	private String name;
    private int age;
	Person(){
        //调用下面的构造方法,如果下面还有代码,必须写在第一行
		this("张三",12);
	}
	Person(String name,int age){
        //调用类中的属性
		this.name=name;
        this.age=age;
	}
}



static:



Java中,是否可以通过类名直接访问类的成员?
  • 使用static关键字可以实现
  • 用 static 修饰的属性、方法和代码块属于它所在的类,由这个类创建的所有对象可以共用同一个static成员
  • 使用static 修饰的属性称为静态变量或类变量
  • 没有使用 static 修饰的属性称为实例变量



Java方法分类

  • 静态方法(又称类方法):使用 static 关键字修饰的方法
  • 实例方法:未使用 static 关键字修饰的方法
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9Zijw4LO-1640223636859)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211223084500805.png)]



static特点

  • 一个类中包含多个static修饰符
  • 当类被加载(初始化对象)按顺序执行
  • 只会执行一遍
  • 静态属性会被多个对象共享



使用static修饰与非static修饰的类成员有哪些不同?


static

、非private修饰



static、private修饰

属性

类属性、类变量

实例属性、实例变量

方法

类方法

实例方法

调用方式
类名.属性 类名.方法() 对象.属性 对象.方法()
对象

属性对象方法()

归属



单个对象


概述:

  • ​ 表示“静态”的意思,可以用来修饰成员变量和成员方法

  • ​ static的主要作用在于创建独立于具体对象的域变量或者方法 。

  1. 静态成员 在类加载时加载并初始化 ;
  2. 无论一个类存在多少个对象 , 静态的属性, 永远在内存中只有一份( 可以理解为所有对象公用 ) ;
  3. 在访问时: 静态不能访问非静态 , 非静态可以访问静态 ;
  4. 静态修饰的方法,被调用时,有可能对象还未创建 ;



final:


final用于修饰属性(类里定义的标识符称为属性)和变量(方法体里定义的标识符成为变量:

  • 通过final修饰的属性和变量都是常量,就是不能再次赋值的变量或属性 ;
  • final修饰的局部变量,只能赋值一次(可以先声明后赋值);
  • final修饰的成员属性,必须在声明时赋值 ;
  • 全局常量(public static final)可以在任何位置被访问 ;
  • 常量的命名规范:由一个或多个单词组成,单词之间必须使用下划线隔开,所有字母大写,例如:SQL_INSERT ;



final用于修饰类:

final修饰的类,不能被继承。



final用于修饰方法:

final修饰的方法,不能被子类重写。



封装


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



而是通过该类提供的方法来实现对隐藏信息的操作和访问

实现封装的具体步骤如下:

  1. 修改属性的可见性来限制属性的访问
  2. 为每个属性创建一对赋值(setter)方法和取值(getter)方法,用于对这些属性的存取
  3. 在赋值方法中,可以加入对属性的存取控制语句
//我们观察如下代码:
class Person{ 
    private String name ; // 表示姓名 
    private int age ;     // 表示年龄 
    void tell(){ 
        System.out.println("姓名:" + name + ";年龄:" + age) ;
    } 
};
public class Demo{ 
    public static void main(String args[]){ 
        Person per = new Person() ;
        per.name = "张三" ;
        per.age = -30 ;
        per.tell() ;
    } 
}; 
//以上的操作代码并没有出现了语法错误,但是出现了逻辑错误 (年龄-30岁) 在开发中, 为了避免出现逻辑错误, 我们建议对所有属性进行封装,并为其提供setter及getter方法进行设置和取得 操作。 修改代码如下:
class Person{ 
    private String name ; // 表示姓名 
    private int age ;     // 表示年龄 
    void tell(){ 
        System.out.println("姓名:" + getName() + ";年龄:" + getAge()) ;
    }
    public void setName(String str){ 
        name = str ; 
    }
    public void setAge(int a){ 
        if(a>0&&a<150) age = a ; 
    }
    public String getName(){ 
        return name ;
    }
    public int getAge(){ 
        return age ; 
    } 
};
public class OODemo10{ 
    public static void main(String args[]){ 
        Person per = new Person() ;
        per.setName("张三") ; 
        per.setAge(-30) ; 
        per.tell() ;
    }
};



封装的好处:

  • 隐藏类的实现细节
  • 只能通过规定方法访问数据
  • 方便加入控制语句
  • 方便修改



封装的步骤:

  • 修改属性的可见性—改为private
  • 创建公有的get/setter方法–用于属性的读写
  • 在get/setter方法中加入属性控制语句–对属性值的合法性进行判断



访问修饰符:

Java中,如何限制和制约类之间的访问关系?

  1. 访问修饰符



类的访问修饰符


修饰符 作用域

同一包中

非同一包中
public 可以使用 可以使用
默认修饰符 可以使用 不可以使用



类成员的访问修饰符:


修饰符 作用域

同一类中

同一包中

子类中

外部包
private 可以使用 不可以使用 不可以使用 不可以使用
默认修饰符 可以使用 可以使用 不可以使用 不可以使用
protected 可以使用 可以使用 可以使用 不可以使用
public 可以使用 可以使用 可以使用 可以使用



类成员的访问修饰符:


修饰符 作用域

同一类中

同一包中

子类中

外部包
private 可以使用 不可以使用 不可以使用 不可以使用
默认修饰符 可以使用 可以使用 不可以使用 不可以使用
protected 可以使用 可以使用 可以使用 不可以使用
public 可以使用 可以使用 可以使用 可以使用



总结

在这里插入图片描述



版权声明:本文为weixin_53469577原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。