JAVA面向对象三条主线:
1.JAVA类和类的成员:属性、构造器、方法、代码块、内部类。
2.面向对象的三大特征:封装性、继承性、多态性
3.其他关键字:this、super、static等等
一、类和对象及定义。
类:对一类事物的描述,是抽象的,比如人、汽车等;
对象:是实际存在的该类事物的每个个体,也被称作实列,比如:具体的某个人,具体的某辆车。
类的定义:
class 类名{
属性;
构造器;
方法;
}
对象的定义:
类名 对象名称 = new 类名() ;
通过对象访问类中的方法或属性:
对象.属性;
对象.方法();
dog.eat();
new Animal().eat();//匿名对象调用方法,
匿名对象:在创建对象的时候,没有赋予一个名称,且只能调用一次。
二、对象的内存解析
1、java中类是属于引用数据类型,引用数据类型与地址有关。比如:
如果变量是基本数据类型,赋值是变量所保存的数据值。
如果变量是引用数据类型,此时赋值是变量所保存的地址的值。(例:Person p2 = p1;p1变量保存的对象地址的值就会赋予给p2,p1和p2堆空间中的同一对象实体,p1.属性的值改变,p2.属性的值也会改变)
2、常用的两块内存空间:堆内存和栈内存。
堆内存:堆允许程序在运行时动态地申请某个大小的内存空间。保存的是对象的具体信息;堆内存空间的开辟是通过new关键字实现的,new有最高级别的开辟内存空间权力。
栈内存:保存的是堆内存的地址;栈有一个很重要的特殊性,就是存在栈中的数据可以共享栈内存在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。即通过地址找到堆内存找到地址
假设一个Dog类,里面有name和age两个属性;
(1)对象在内存中的结构: Dog dog = null; Dog dog = new Dog();
(2)对象之间的赋值:Dog dog1 = new Dog(); Dog dog2 = new Dog();
dog1 = dog2; dog2.name = "卡卡";
具体例子:
3、内存小结:
(1)new关键字:表示向内存申请空间,也表示实例化一个对象;
(2)一个对象在内存中的大小,由该对象的所有属性所占的内存大小的总和;
(3)不同的引用,指向同一个对象,任何一个引用改变对象的值,其它引用都会反映出来
(4)编程时要注意的问题,在确定不使用对象时,要尽早释放对象:引用=null;
(5)当一个堆中的对象没有被任何引用变量所指向时,该对象会被JVM 的 GC 程序认为是垃圾对象,从而被回收;
三、方法
1、方法的重载
在一个类中,允许存在一个以上的同名方法,只要他们的参数个数或者参数类型不同即可。
test.getsum(1,2)
/*public void getsum(int i,int j){
System.out.println(i+j);
}*/
public void getsum(double i,double j){
System.out.println(i+j);
}
//当上面的方法打开后,会优先执行上面的方法。
2、值传递机制
(1)形参:方法定义时,声明在小括号内的参数;
实参:方法调用时,实际传递给形参的数据;
(2)值传递机制:
如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据;
如果参数是引用数据类型,此时实参赋给形参的是实参址存储数据的地;
(3)内存中的加载位置
属性:加载到堆内存中(非static)
局部变量:加载到栈内存中
//正确,交换数组中指定两个位置的值
private static void swap(int[] a, int i, int j) {
int t = a[i];
a[i] = a[j];
a[j] = t;
}
//错误
private static void swap(int i, int j) {
int t = i;
i = j;
j = t;
}
3、方法参数传递练习
三、封装性
1.高内聚,低耦合
高内聚:类的内部数据操作细节自己完成,不允许外部干涉。
低耦合:仅对外部暴露少量的方法用于使用。
2.封装性的体现
(1)将类的属性设为私有化(private)提供公共的方法来获取和设置值(get、set方法);
(2)不对外暴露的私有方法。
(3)单列模式等等。
修饰符:
注:对于class的权限修饰符,只能用public和default(缺省)
四、构造器
1.构造器的作用
创建对象,初始化对象信息。
2.特征
它具有与类相同的名称,它不声明返回值类型,权限和类一样。
//无参
public 类名(){}
//有参
public 类名(String name){
this.name = name;
}
3.说明
如果没有显示的定义类的构造器,系统会默认提供一个空参的构造器。如果有显示构造器,那么默认的那个将无效。最好把空参的构造器补上.
在构造方法中调用另一个构造方法,使用this(...),该句代码必须在第一句。
五、this关键字
1.this的作用
this可以理解为当前对象或者正在创建的对象
this可用来修饰属性、方法、构造器
在类的方法中,我们可以使用“this.属性”或“this.方法”的方式,调用当前对象属性或方法,通常情况下省略。如果方法的参数和类的属性相同时,这时就必须使用this.属性, 来代表该类中的属性。
2.this调用构造器
我们在类的构造器中,可以显示的使用"this(形参列表)",来调用本类中其他构造器。
构造器中不能调用自己。
如果一个类中有n个构造器,则最多有n-1个构造器中使用了“this(形参列表)”,不然会出现死循环。
"this(形参列表)"必须在首行,且最多只能有一个。
五、import关键字
在源文件中使用import显式的导入指定包的类或接口
声明在包的声明和类的声明之间
如果需要导入多个类或接口,那么就并列显式多个import语句即可
例如可以使用java.util.*的方式,一次性导入util包下所有的类或接口
如果导入的类或接口是java.lang包下的,或者是当下包下,则可以省略此import语句
如果在代码中使用不同包下的同名类,那么就需要使用类的全类名的方式指明调用的是哪个类
如果已经导入java.a包下的类,那么如果需要使用a包的子包下的类的话,仍需要导入
import static组合的使用:调用指定类或接口下的静态属性或方法
练习:
Account类
public class Account {
private double balance;//余额
public Account(double balance) {
super();
this.balance = balance;
}
public double getBalance() {
return balance;
}
//存钱操作
public void deposit(double amt) {
if(amt > 0){
this.balance+=amt;
System.out.println("存钱成功 ");
}
}
//取钱操作
public void withdraw(double amt) {
if(balance < amt){
System.out.println("余额不足");
return;
}
this.balance-=amt;
System.out.println("取钱成功");
}
}
Bank类
public class Bank {
private Customer[] customers = new Customer[10];//存放多个客户的数组
private int numberOfCustomers;//记录客户的数量
//添加客户
public void addCustomer(String f,String l) {
Customer cust = new Customer(f, l);
customers[numberOfCustomers++] = cust;
}
//获取客户的个数
public int getNumOfCustomers() {
return numberOfCustomers;
}
//获取指定位置上的客户
public Customer getCustomer(int index) {
//return customers[index];直接写可能报异常
if(index >=0 && index < numberOfCustomers){
return customers[index];
}
return null;
}
}
Customer类
public class Customer {
private String firstName;
private String lastName;
private Account account;
public Customer(String firstName, String lastName) {
super();
this.firstName = firstName;
this.lastName = lastName;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
}
Test类
public class Test {
public static void main(String[] args) {
Bank bank = new Bank();
bank.addCustomer("Jane","Smith");
bank.getCustomer(0).setAccount(new Account(2000));
bank.getCustomer(0).getAccount().withdraw(500);
double balance = bank.getCustomer(0).getAccount().getBalance();
System.out.println("客户 :"+bank.getCustomer(0).getFirstName()+" 账户余额为 :"+balance);
System.out.println("--------------");
bank.addCustomer("dudu", "lala");
System.out.println("银行的客户数 :"+bank.getNumOfCustomers());
}
}
输出:
取钱成功
客户 :Jane 账户余额为 :1500.0
--------------
银行的客户数 :2