java面向对象编程(基础)
java面向对象编程(基础)
Jin面向对象的程序设计思想
- 类 :在计算机程序设计过程中,参照现实中事物,将事物的属性特征、行为特征抽 象出来,用类来表示。
- 典型的语言:Java、C#、C++、Python、Ruby和PHP等 代码结构:以 类 为组织单位。
- 每种事物都具备自己的 属性 和 行为/功能 。
- 是一种“设计者思维 ,适合解决复杂问题。代码扩展性强、可维护性高。
面向对象特征
封装、继承、多态、(抽象)
面向对象例子
把猪肉放进冰箱
面向过程的做法
1.打开冰箱
2.把猪肉装进冰箱
3.把冰箱门关住
面向对象的做法
人{
打开(冰箱){
冰箱.开门();
}
操作(猪肉){
猪肉.进入冰箱();
}
关闭(冰箱){
冰箱.关门();
}
}
冰箱{
开门();
关门();
}
猪肉{
进入冰箱();
}
类和对象
类(Class) 和 对象(Object) 是面向对象的核心概念
什么是类
类:具有相同特征的事物的抽象描述,是 抽象的 、概念上的定义
什么是对象
对象:实际存在的该类事物的 每个个体 ,是 具体的 ,因而也称为
实例(instance)
简单理解:类的一个抽象概念的一个人,对象是实实在在的一个人
类的定义
使用关键字 class
class [类名]{
属性声明;
方法声明;
}
例如创建一个猫类
class cat{
// 属性声明
String name;
int age;
// 方法声明
public void eat(){ System.out.println("猫吃东西~~"); }
}
对象的创建
使用关键字 new
对象的创建也称为类的实例化
使用对象名.属性
或 对象名.方法
的方式访问对象成员(包括属性和方法)
//方式1:给创建的对象命名
//把创建的对象用一个引用数据类型的变量保存起来,这样就可以反复使用这个对象了
类名 对象名 = new 类名();
//方式2:
new 类名()//也称为匿名对象
例如实例化一个猫类 / 创建一个猫对象
class CatTest{
public static void main(String[] args){
//创建Cat类的对象
Cat cat1 = new Cat();
// 访问对象属性和方法
cat1.age = 12;
System.out.printIn("cat age is" + cat1.age);
cat1.eat();
// 创建第二个Cat类对象
Cat cat2 = new Cat();
// 访问对象属性和方法
cat2.age = 9;
System.out.printIn("cat age is" + cat2.age);
cat2.eat();
}
}
属性如果不赋值,有默认值,规则和数组一致
具体: int 0,short 0, byte 0, long 0, float 0.0,double 0.0,char 0, boolean false,String null
对象内存解析
jvm 内存解析图
- 堆:凡是new出来的结构(对象、数组)都放在堆空间中
- 对象的属性存放在堆空间中
- 创建一个类的多个对象(比如cat1,cat2),则每个对象都拥有当前类的一套”副本”(即属性)
- 当通过一个对象修改其属性时,不会影响其它对象此属性的值。
- 当声明一个新的变量使用现有的对象进行赋值时(比如cat3 = cat1),此时并没有在堆空间中创 建新的对象,而是两个变量共同指向了堆空间中同一个对象
- 当通过一个对象修改属性时, 会影响另外一个对象对此属性的调用
成员变量
语法格式
[修饰符1] class 类名{
[修饰符2] 数据类型 成员变量名 [= 初始化值];
}
- 位置要求:必须在类中,方法外
- 修饰符常用的权限修饰符有:private、缺省、protected、public 其他修饰符:static、final
- 数据类型 任何基本数据类型(如int、Boolean) 或 任何引用数据类型
- 成员变量名 属于标识符,符合命名规则和规范即可
- 初始化值 根据情况,可以显式赋值;也可以不赋值,使用默认值
例如
public class Person{
private int age; //声明private变量 age
public String name = “Lila”; //声明public变量 name
}
局部变量
在方法体内部等位置声明的变量称为局部变量,局部变量作用域只在方法体内部 / 代码块
public class Person{
int age; // 成员变量
public void sayHello(){
String msg = "hello"; // 局部变量
System.out.printIn(msg);
}
}
成员变量和局部变量的不同
作用域 (1)实例变量:通过对象就可以使用,本类中直接调用,其他类中 “对象.实例变量”(2)局 部变量:出了作用域就不能使用
在内存中存储的位置不同 (1)实例变量:堆 (2)局部变量:栈
修饰符 (1)实例变量:public,protected,private,final,volatile,transient等 (2)局部变 量:final
默认值 (1)实例变量:有默认值 (2)局部变量:没有,必须手动初始化。其中的形参比较特殊, 靠实参给它初始化。
this 关键字
哪个对象调用,this就代表哪个对象
当形参与成员变量同名时,如果在方法内或构造器内需要使用成员变量,必须添加 this 来表明该变量是类的成员变量
我们可以用 this 来区分 成员变量和局部变量
比如
class Cat{
String name;
public void setName(String name){
// this.name 表示成员变量 / 属性
// 后面的 name 表示传进来的形参 即局部变量
this.name = name;
}
}
this 可以作为一个类中构造器相互调用的特殊格式
比如
public class Student {
private String name;
private int age;
// 无参构造
public Student() {
// this("",18);//调用本类有参构造器
}
// 有参构造
public Student(String name) {
this();//调用本类无参构造器
this.name = name;
}
// 有参构造
public Student(String name,int age){
this(name);//调用本类中有一个 String 参数的构造器
this.age = age;
}
}
方法
方法的概念
方法 是类或对象行为特征的抽象,用来完成某个功能操作。在某些语言中也称为 函数 或 过程 。
将功能封装为方法的目的是,可 实现代码重用,减少冗余,简化代码 Java里的方法 不能独立存在
所有的方法必须定义在类里
语法格式
[修饰符] 返回值类型 方法名([形参列表])[throws 异常列表]{
方法体的功能代码
}
例如
public class Person {
public static void main(String[] args) {
Person p1 = new Person();
p1.eat();
}
public static void eat() {
sleep();
System.out.println("人:吃饭");
}
public static void sleep(){
System.out.println("人:睡觉");
doSport();
}
public static void doSport(){
System.out.println("人:运动");
}
}
内存分析
方法重载
- 方法重载:在同一个类中,允许存在一个以上的同名方法,只要它们的参数列表不同即可
- 重载的特点:与修饰符、返回值类型无关,只看参数列表,且参数列表必须不同。(参数个数或参 数类型)。调用时,根据方法参数列表的不同来区别。
- 重载方法调用:JVM通过方法的参数列表,调用匹配的方法。 先找个数、类型最匹配的 再找个数和类型可以兼容的,如果同时多个方法可以兼容将会报错
举例说明
//返回两个整数的和
public int add(int x,int y){
return x+y;
}
//返回三个整数的和
public int add(int x,int y,int z){
return x+y+z;
}
//返回两个小数的和
public double add(double x,double y){
return x+y;
}
注意:方法的重载和返回值类型无关
可变个数的形参
当定义一个方法时,形参的类型可以 确定,但是形参的个数不确定,那么可以考虑使用可变个数的形参
格式:
方法名(参数的类型名 ...参数名)
例如:
//JDK5.0:采用可变个数形参来定义方法,传入多个同一类型变量
public static String test(char seperator ,String...books){
String str = "";
for (int i = 0; i < books.length; i++) {
if(i==0){
str += books[i];
}else{
str += seperator + books[i];
}
}
return str;
}
String...
表示接受的是可变参数,类型是String
,即可以接收多个String
使用可变参数时候,可以当数组来使用,books
可以当做数组
形参和实参
形参(formal parameter):在定义方法时,方法名后面括号()中声明的变量称为形式参数,简称形参
实参(actual parameter):在调用方法时,方法名后面括号()中的使用的值/变量/表达式称 为实际参数,简称实参
行参的值传递根据数据类型来传递的
基本数据类型:将实参基本数据类型变量的数据值
传递给形参
引用数据类型:将实参引用数据类型变量的地址值
传递给形参
package
package,称为包,用于指明该文件中定义的类、接口等结构所在的包
package pack1.pack2; //指定类 PackageTest 属于包 pack1.pack2
public class PackageTest{
public void display(){
System.out.println("in method display()");
}
}
说明:
一个源文件只能有一个声明包的 package 语句
包名,属于标识符,满足标识符命名的规则和规范(全部小写)、见名知意,取包名时不能使用
java.xx
包包对应于文件系统的目录,package 语句中用
.
来指明包(目录)的层次,每.
一次就 表示一层文件目录同一个包下可以声明多个结构(类、接口),但是不能定义同名的结构(类、接口)
不同的包下可以定义同名的结构(类、接口)
import
为了使用定义在其它包中的 Java 类,需用 import 语句来显式引入指定包下所 需要的类
语法格式:import 包名.类名
说明:
- 如果使用
a.*
导入结构,表示可以导入 a 包下的所有的结构 - 如果导入的类或接口是
java.lang
包下,或者是当前包下的,则可以省略 import 语句 - 如果在代码中使用不同包下的同名的类,那么就需要使用类的全类名的方式指明调用 的是哪个类
封装性
把客观事物封装成抽象概念的类,并且类可以把自己的数据和 方法只向可信的类或者对象开放,向没必要开放的类或者对象隐藏信息
通俗的讲,把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想
权限修饰符
实现封装就是控制类或成员的可见性范围。这就需要依赖访问控制修饰符,也称为权限修饰符来控制
修饰符 | 本类内部 | 本包内 | 其他包的子类 | 其他包非子类 |
---|---|---|---|---|
private | ✅ | ❌ | ❌ | ❌ |
protected | ✅ | ✅ | ❌ | ❌ |
public | ✅ | ✅ | ✅ | ❌ |
省 | ✅ | ✅ | ✅ | ✅ |
具体修饰的结构:
- 外部类:public、缺省
- 成员变量、成员方法、构造器、成员内部类:public、protected、缺省、 private
私有化
成员变量私有化
私有化类的成员变量,提供公共的 get 和 set 方法,对外暴露获取和修 改属性的功能
例如
public class Book {
// 1.使用 private 修饰成员变量
private String bookName;
private double price;
// 2.提供 getXxx 方法 / setXxx 方法,可以访问成员变量,
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
public class BookTest {
public static void main(String[] args) {
Book book = new Book();
// 使用 set/get 访问成员变量
book.setBookName("红楼梦");
book.setPrice(12.2);
System.out.println("book name is "+book.getBookName()+
", price is "+book.getPrice());
}
}
构造器
new 对象,并在 new 对象的时候为实例变量赋值
语法格式
[修饰符] class 类名{
[修饰符] 构造器名(){
// 实例初始化代码
}
[修饰符] 构造器名(参数列表){
// 实例初始化代码
}
}
例如
public class Cat{
private String catName;
private int age;
public Cat(String catName, int age){
this.catName = catName;
this.age = age;
}
}
public class catTest{
public static void main(String[] args) {
//调用无参构造创建
Cat cat1 = new Cat();
//调用有参构造创建
Cat cat2 = new Cat("喵喵",12);
}
}
说明:
- 构造器名必须与它所在的类名必须相同
- 它没有返回值,所以不需要返回值类型,也不需要 void
- 构造器的修饰符只能是权限修饰符,不能被其他任何修饰。比如,不能被 static、 final、synchronized、abstract、native 修饰,不能有 return 语句返回值
- 当我们显式的定义类的构造器以后,系统就不再提供默认的无参的构造器了。 在类中,至少会存在一个构造器。 构造器是可以重载的
参考资料