Java 面向对象(上)

面向对象(上)

一、 Java 面向对象学习的三条线

1. Java类及类的成员

属性、方法、构造器、代码块、内部类

2. 面向对象的三大特征

① 封装性
② 继承性
③ 多态性(抽象性)

3. 其他关键字

this、super、static、final、abstract、interface、package、import

二、面向对象的两个要素

类:对一类事物的描述,是抽象的、概念上的定义
对象:是实际存在的该类事物的每个个体,因而也称为实例(instance)
面向对象程序设计的重点是类的设计
设计类,就是设计类的成员
类和对象二者的关系:
对象,是由类new出来的,或者说是派生出来的。

三、设计类,其实就是设计类的成员

属性 == 成员变量 == filed == 域、字段
方法 == 成员方法 == 函数 == method
创建类的对象 == 类的实例化 == 实例化

四、类和对象的使用( 面向对象思想落地的实现 )

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

五、对象的创建与对象的内存解析

典型代码:

Person p1 = new Person();
Person p2 = new Person();
Person p3 = p1;//没有新创建一个对象,共用一个堆空间的对象实体。

说明:

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

public class PersonTest {
public static void main(String[]args){
//2. 创建一个Person类的对象
Person p1 = new Person();
//3. 调用对象的结构:属性、方法
//调用属性:“对象.属性 ”
p1.name = "Tom";
p1.age = 2;
p1.isMale = true;
System.out.println(p1.name);

//调用方法:" 对象.方法 "
p1.eat();
p1.sleep();
p1.talk("Chinese");

//********************************
Person p2 = new Person();
System.out.println(p2.name); // null
System.out.println(p2.isMale);// false
//********************************
//将p1变量保存的对象地址赋予给p3,导致p1和p3指向了堆空间中的同一个对象实体。
Person p3 = p1;
System.out.println(p3.name); //Tom

p3.age = 10;
System.out.println(p1.age); // 10

}

}

//1.创建类,设计类的成员
class Person{
// 属性
String name;
int age;
boolean isMale;

//方法
public void eat(){
System.out.println("人可以睡觉");
}
public void sleep(){
System.out.println("人可以睡觉");
}
public void talk(String languge){
System.out.println("人可以说话,使用的是: " + languge);
} 
}

输出结果:
Tom
人可以睡觉
人可以睡觉
人可以说话,使用的是: Chinese
null
false
Tom
10

六、类中属性的使用

6.1. 属性(成员变量)与 局部变量的相同点和不同点

6.1.1 相同点:

a) 定义变量的格式:数据类型 变量名 = 变量值
b) 先声明变量,后使用
c) 变量都有其对应的作用域

6.1.2 不同点:

a) 在类中声明的位置不同
属性: 直接定义在类的一对{}内
局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量
b) 关于权限修饰符的不同
属性:可以声明属性时,指明其权限,使用权限修饰符。
常用的权限修饰符:private、public、缺省、protected —> 封装性
局部变量: 不可以使用权限修饰符
c) 默认初始化值得情况:
属性:类的属性,根据其类型,都有默认初始化值。
整型(byte、short、int、long):0
浮点型(float、double): 0.0
字符型 (char):0 (或’\u0000‘)
布尔型(boolean):false
引用数据类型 (类、数组、接口):null
局部变量:没有默认初始化值。
意味着,我们在调用局部变量之前,一定显示赋值、
特别地:形参在调用时,我们赋值即可
d) 在内存中加载的位置
属性: 记载到堆空间中(非static)
局部变量:加载到栈空间
代码:

package ys.com.java;

public class UserTest {
public static void main(String[] args) {
User p1 = new User();
System.out.println("==========默认初始化值:");
System.out.println(p1.name);
System.out.println(p1.age);
System.out.println(p1.isMale);
System.out.println("==========类的调用:");
p1.talk("汉语");
p1.eat();
}
}


class User{
//属性(或成员变量)
String name;
int age;
boolean isMale;

public void talk(String language){//language 形参,也是局部变量
System.out.println("我们使用"+ language + "进行交流");
}

public void eat(){
String food = "烙饼";//局部变量
System.out.println("北方人喜欢吃:" +food);
}
}

输出结果:
==========默认初始化值:
null
0
false
==========类的调用:
我们使用汉语进行交流
北方人喜欢吃:烙饼

七、类方法的声明和使用

方法:描述类应该具有的功能
如: Math类:sqrt()、random() …
Scanner类:nextXxx()…
Arrays类:sort()、binarySearch()、toString()、equals()…
4. 举例:
public void eat(){}
public void sleep(int hour){}
public String getName(){}
public String getNation(String nation){}

  1. 方法的声明格式:
    权限修饰符 返回值类型 方法名(形参列表){
    方法体
    }
  2. 说明:
    3.1 关于权限修饰符:默认方法的权限修饰符都使用public
    Java规定的4种权限修饰符:private、public、缺省、protected —> 封装性
    3.2 返回值类型:有返回值 和 没有返回值
    i. 如果有返回值,则必须在方法声明时,指定返回值的类型。同时,方法中需要使用return关键字来返回指定类型的变量或常量。“return 数据”
    ii. 如果方法没有返回值,则方法声明时,使用void来表示。通常,没有返回值的方法中,就不使用return。但是如果使用的话,只能“return;”表示结束此方法的意识。
    iii. 我们定义的方法该不该返回值?
    a) 题目要求
    b) 凭经验,具体问题具体分析
    3.3 方法名:属于标识符,遵循标识符的规则和规范,“见名知意”
    3.4 形参列表: 方法可以声明0个、1个、或多个形参。
    iv. 格式: 数据类型1 形参1,数据类型2 形参2, …
    v. 我们定义方法时,该不该定义形参
    a) 题目要求
    b) 凭经验,具体问题具体分析
    3.5 方法体:方法功能的体现
  3. return关键字的使用:
    b) 使用范围:使用在方法体中
    c) 作用:
  4. 结束方法
  5. 针对有返回值类型的方法,使用“return 数据”方法返回所要的数据。
  6. 注意点:return关键字后面不可以声明执行语句
  7. 方法的使用中,可以调用当前类的属性或方法
    特殊的: 方法A中有调用了方法A:递归方法。
    注: 方法中,不可以定义方法
    代码:
package ys.com.java;



public class CustomerTest {
public static void main(String[] args) {
//创建Customer对象
Customer cust = new Customer();
//类的调用

cust.eat();
cust.sleep(10);

}
}

class Customer{
//属性
String name;
int age;
boolean isMale;

//方法
public void eat(){
System.out.println("客户吃饭");
}

public void sleep(int hour){
System.out.println("休息了" + hour +"个小时");
eat();
}

public String getName(){
return name;
}

public String getNation(String nation){
String info = "我的国籍是:" + nation;
return info;
}

}

输出结果:
客户吃饭
休息了10个小时
客户吃饭

八、理解“万事万物皆对象”

  1. 在Java语言范畴中,我们都将功能、结构等封装到类中,通过类的实例化,类调用具体的功能结构
    a) Scanner、String等
    b) 文件:File
    c) 网络资源:URI
  2. 涉及到Java语言与前端(Html、JS、CSS)、后端的数据库交互时,前后端的结构在Java层面交互时,都有体现类、对象。

九、内存解析说明

  1. 引用类型的变量,只可能存储两类值:null 或者 地址值(含变量的类型)

十、匿名对象的使用

  1. 理解:我们创建的对象,没有显式的赋给一个变量名。即为匿名对象
  2. 特征:匿名对象只能调用一次。
  3. 使用:如下
    代码:
public class InstanceTest {
public static void main(String[] args) {
Phone p = new Phone();
//p = null;
System.out.println(p);

p.sendEmail();
p.playGame();


//匿名对象
//new Phone().sendEmail();
//new Phone().playGame();

new Phone().price = 1999;
new Phone().showPrice();//0.0

//**********************************
PhoneMall mall = new PhoneMall();
//mall.show(p);
//匿名对象的使用
mall.show(new Phone());

}
}

class PhoneMall{


public void show(Phone phone){
phone.sendEmail();
phone.playGame();
}

}


class Phone{
double price;//价格

public void sendEmail(){
System.out.println("发送邮件");
}

public void playGame(){
System.out.println("玩游戏");
}

public void showPrice(){
System.out.println("手机价格为:" + price);
}

}

十一、变量的赋值

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

public class ValueTransferTest {
public static void main(String[] args) {
System.out.println("***基本数据类型****");
int m = 10;
int n = m;

System.out.println("m = "+ m +",n = "+ n);

n = 20;

System.out.println("m = "+ m +",n = "+ n);

System.out.println("***引用数据类型****");
Order o1 = new Order();
o1.orderID = 1001;
Order o2 = o1;//赋值以后,o1和o2的地址值相同,都指向了堆空间中同一个对象实体。
System.out.println("o1.orderID = "+ o1.orderID +" o2.orderID = "+ o2.orderID);

o2.orderID = 1002;
System.out.println("o1.orderID = "+ o1.orderID +" o2.orderID = "+ o2.orderID);


}
}



class Order{
int orderID;
}

执行结果:
m = 10 , n = 10
m = 10 , n = 20
o1.orderID = 1001 , o2.orderID = 1001
o1.orderID = 1002 , o2.orderID = 1002

十二、方法的形参的传递机制:值传递

  1. 形参: 方法定义时,声明的小括号内的参数
  2. 实参: 方法调用时,实际传递给形参的数据
  3. 值传递机制:
    a) 如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值。
    b) 如果参数是引用数据类型,此时实参赋给形参的是实参存储数据的地址值。
public class ValueTransferTest1 {
public static void main(String[] args) {
int m = 10;
int n = 20;

System.out.println("m = "+ m +",n = "+ n);

ValueTransferTest1 test = new ValueTransferTest1();
test.swap(m, n);
System.out.println("m = "+ m +",n = "+ n);
}

public void swap(int m,int n){
int temp = m;
m = n;
n = temp;
}

}

执行结果:
m = 10 , n = 20
package ys.com.java1;

public class ValueTransferTest2 {
public static void main(String[] args) {
Data data = new Data();
data.m = 10;
data.n = 20;

System.out.println("m = "+ data.m +", n = "+data.n);

ValueTransferTest2 test2 = new ValueTransferTest2();
test2.swap(data);
System.out.println("m = "+ data.m +", n = "+data.n);

}

public void swap(Data data){
int temp = data.m;
data.m = data.n;
data.n = temp;
}

}


class Data{

int m;
int n;

}


执行结果:
m = 10 , n = 20
m = 20 , n = 10

十三、方法的重载(overload)

  1. 定义:
    a) 在同一个类中,允许存在一个以上的同名方法,只要他们的参数个数或者参数类型不同即可。
    “ 两同一不同 ”:
    同一类,相同的方法名;
    参数列表不同:参数的个数不同、参数类型不同。
  2. 举例:
    a) Arrays类型中重载的sort() 、binarysearch()。
  3. 判断是否是重载:
    跟方法的权限修饰符、返回值类型、形参变量名、方法体都没有关系。
  4. 在通过对象调用时,如何确定某一个指定的方法:
    方法名 —> 参数列表
    代码:
public class OverLoadTest {
public static void main(String[] args) {
OverLoadTest test = new OverLoadTest();
test.getSum(1,2);
test.getSum(1.2,2);
test.getSum("asd", "asda");
test.getSum(1, "asda");
//错误的调用
//test.getSum("asda",1);

}


// 如下的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 i,String j){
System.out.println("3");
}

public void getSum(int i,String j){
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){
//
//}
}

十四、递归的使用

  1. 递归方法:一个方法体调用他自身
  2. 方法递归包含了一种隐式的循环,它会重复的中旬某段代码,但是这种重复执行无须循环控制,递归一定要想已知方向递归,否则这种递归就变成了无限递归,类似于死循环。
    代码:
public class RecursionTest {
public static void main(String[] args) {
// 例1: 计算1-100之间所有自然数的和
// 方式一:
System.out.println("---------方式一-------------");
int sum = 0;
for(int i = 0;i <= 100;i++){
sum += i;
}
System.out.println(sum);

System.out.println("---------方式二-------------");
// 方式二:
RecursionTest test = new RecursionTest();
int sum1 = test.getSum(5);
System.out.println(sum1);


System.out.println("---------例2-------------");
int value = test.f(10);
System.out.println(value);


}

// 方式二:计算1-n之间所有自然数的和
public int getSum(int n){
if(n == 1){
return 1;
}else {
return n + getSum(n -1);
}
}

//例2:已知有一个数列:f(0) = 1,f(1) = 4,f(n+2)=2*f(n+1) + f(n),
//其中n是大于0的整数,求f(10)的值。
public int f(int n){
if(n == 0){
return 1;
}else if(n == 1){
return 4;
}else {
return 2*f(n -1) + f(n -2);
}
}

}

十五、面向对象的特征一: 封装与隐藏

  1. 问题的引入:
    当我们创建一个类的对象以后,我们可以通过“对象.属性”的方式,对对象的属性进行赋值。这里赋值操作要受到属性的数据类型和存储范围的制约。除此之外,没有替他制约条件。但是,在实际问题中,我们往往需要给属性赋值加入额外的限制条件,这个条件就不能在属性声明时体现,我们只能通过方法进行限制条件的添加。(比如:setLegs())同时,我们需要避免用户再使用“对象.属性”的方式对属性进行赋值。则需要将属性声明为私有的(private)。–>此时,针对于属性就体现了封装性。
  2. 封装性的体现:
    我们将类的属性xxx私有化(private),同时,提供公共的(public)方法来获取(getXxx)和设置(setXxx)此属性的值
    括展:封装性的体现:
    a) 如上
    b) 不对外暴露的私有方法
    c) 单例模式
  3. 封装性的体现,需要权限修饰符来配合
    a) Java规定的4种权限(从小到大排列):private、缺省、protected、public
    b) 4种权限可以用来修饰类及类的内部结构:属性、方法、构造器、内部类
    c) 具体的,4种权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类
    修饰类的话,只能使用:缺省、public
  4. 总结封装性:
    Java提供了4中权限修饰符来修饰类及类的内部结构,体现类及类的内部结构在被调用时的可见性的大小。
    代码:
public class AnimalTest {
public static void main(String[] args) {
Animal test = new Animal();
test.name = "大黄";
//test.age = 1; //The field Animal.age is not visible

test.show();

test.setAge(2);
test.setLegs(4);
//test.setLegs(-4);
test.show();

System.out.println(test.name);

}
}

class Animal{
String name;
private int age;
private int legs;//腿的个数

//对属性的设置
public void setLegs(int l){
if(l >= 0 && l % 2 == 0){
legs = l;
}else {
legs = 0;
}
}

public int getLegs(){
return legs;
}

public void eat(){
System.out.println("动物进食");
}

public void show(){
System.out.println("name = "+ name +", age = "+ age +",legs = "+legs);
}

//提供关于属性age的get和set方法
public int getAge(){
return age;
}

public void setAge(int a){
age = a;
}
}

十六、类的结构之三:构造器(或构造方法、constructor)的使用

  1. 构造器的作用:
    a) 创建对象
    b) 初始化对象
  2. 说明:
    a) 如果没有显式的定义类的构造器的话,则系统默认提供一个空参的构造器
    b) 定义构造器的格式: 权限修饰符 类名(形参列表){}
    c) 一个类中定义的对一个构造器,彼此构成重载
    d) 一但我们显示的定义了类的构造器之后,系统就不再提供默认的空参构造器
    e) 一个类中,至少会有一个构造器
    代码:
public class PresonTest {
public static void main(String[] args) {
//创建类的对象: new +构造器
Person p = new Person();

p.eat();

Person p1 = new Person("tom");
System.out.println(p1.name);
}
}

class Person{
//属性
String name;
int age;

//构造器
public Person(){

}

public Person(String n){
name = n;
}

public Person(int a){
age = a;
}

public Person(String n,int a){
name = n;
age = a;
}

public void eat(){
System.out.println("人吃饭");
}

public void study(){
System.out.println("人可以学习");
}
}
  1. 总结:属性赋值的先后顺序
    a) 默认初始化
    b) 显式初始化
    c) 构造器中初始化
    d) 通过“对象.方法”或“对象.属性”的方式,赋值
    以上操作的先后顺序:1 --> 2 --> 3 --> 4
    代码:
public class UserTest {
public static void main(String[] args) {
User u = new User();

System.out.println(u.age);

User u1 = new User();

u1.setAge(3);
u1.setAge(5);
System.out.println(u1.age);


}
}


class User{
String name;
int age = 1;

public User(){

}

public User(int a){
age = a;
}

public void setAge(int a){
age = a;
}
}
  1. JavaBean
    JavaBean是一种Java语言写成的可重用组件。所谓JavaBean,是指符合如下标准的Java类:
    a) 类是公共的
    b) 有一个无参的公共的构造器
    c) 有属性,且有对应的get、set方法
    代码:
public class Customer {
private int id;
private String name;

public Customer(){

}

public void setId(int i){
id = i;
}

public int getId(){
return id;
}

public void setName(String n){
name = n;
}

public String getName(){
return name;
}
}

十七、this 关键字的使用

  1. this可以用来修饰(调用):属性、方法、构造器
  2. this修饰属性和方法:
    this理解为:当前对象 或 当前正在创建的对象
    a) 在类的方法中,我们可以使用“this.属性”或者“this.方法”的方式,调用当前对象属性或方法。但是,通常情况下,我们都选择省略“this.”。特殊情况下,如果方法的形参和类型的属性同名时,我们必须显式的使用“this.变量”的方式,表明此变量是属性,而非形参。
    b) 在类的构造器中,我们可以使用“this.属性”或者“this.方法”的方式,调用当前对象属性或方法。但是,通常情况下,我们都选择省略“this.”。特殊情况下,如果构造器的形参和类型的属性同名时,我们必须显式的使用“this.变量”的方式,表明此变量是属性,而非形参。
  3. this调用构造器
    a) 我们在类的构造器中,可以显式的使用“this(形参列表)”的方式,调用本类中指定的其他构造器
    b) 构造器中不能通过“this(形参列表)”方式调用自己
    c) 如果一个类中有n个构造器,则最多有n -1 构造器中使用了“this(形参列表)”
    d) 规定:“this(形参列表)”必须声明在当前构造器的首行
    e) 构造器内部,最多只能声明一个“this(形参列表)”,用来调用其他构造器
    代码:
public class PersonTest {
public static void main(String[] args) {
Person test = new Person();

test.setAge(3);
System.out.println("age = " + test.getAge());

Person test2 = new Person("Tom",4);
System.out.println(test2.getAge());
}
}

class Person{
private String name;
private int age;

public Person(){
System.out.println("Person初始化时,需要考虑如下的1,2,3,4...(共40行代码)");
}

public Person(String name){
this();
this.name = name;
}

public Person(int age){
this();
this.age = age;
}

public Person(String name,int age){
this(age);
//this.age = age;
this.name = name;
}

public void setName(String name){
this.name = name;
}

public String getName(){
return this.name;
}

public void setAge(int age){
this.age = age;
}

public int getAge(){
return this.age;
}

public void eat(){
System.out.println("人吃饭");
this.study();
}

public void study(){
System.out.println("人可以学习");
}

}

十八、package关键字的使用

  1. 为了更好的实现项目中类的管理,提供包的概念
  2. 使用package声明类或者接口所属的包,声明在源文件的首行
  3. 包,属于标识符,遵循标识符的命名规则、规范(xxxzzzrr)、“见名知其意”
  4. 每“.”一次,就代表一层文件目录
    补充: 同一个包下,不能命名同名的接口、类
    不同的报下,可以命名同名的接口、类

十九、import关键字的使用(import 导入)

  1. 在源文件中显式的使用import结构导入指定包下的类、接口
  2. 声明在包的声明和类的声明之间
  3. 如果需要导入多个结构,则并列写出即可
  4. 可以使用“xxx.*” 的方式,表示可以导入xxx包下的所有结构
  5. 如果使用的类或者接口是java.lang包下定义的则可以省略import结构
  6. 如果使用的类或者接口是本宝下定义的,则可以省略import结构
  7. 如果在源文件中,使用了不同报下的同名的类,则必须执行有一个类需要以全类名的方式显示
  8. 使用“xxx.*”方式表明可以调用xxx包下的所有结构。但是如果使用的是xxx子包下的结构,则仍需要显式导入
  9. import static:导入指定类或接口中的静态结构:属性或方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值