目录
一、面向对象基本概念
1、什么是面向对象:
面向对象是一种编程思想。
面向对象是一种思考问题的思维方式
2、建立面向对象思维方式
先整体,再局部
先抽象,再具体
能做什么,再怎么做
二、类与对象
1、什么是类
类:分类、分别;
通过分类,我们可以区别不同的事物种类;
所以,类是一组具有相同特性(属性)与行为(方法)的事物集合;
2、类与对象的关系
类表示一个共性的产物,是一个综合的特征,而对象,是一个个性的产物,是一个个体的特征。
类由属性和方法组成:
属性:就相当于一个个的特征
方法:相当于人的一个个的行为,例如:说话、吃饭、唱歌、睡觉;
3、类和对象的定义格式
在java中可以使用以下的语句定义一个类:
class 类名称{
属性名称;
返回值类型 方法名称(){};
}
对象的定义:
一个类要想真正的进行操作,则必须依靠对象,对象的定义格式如下:
类名称 对象名称 = new 类名称();
如果想要访问类中的属性和方法(方法的定义),可以依靠下面的语法形式
访问类中的属性:
对象.属性;
访问类中的方法:
对象.方法();
public class Test{
public static void main(String[] args){
//用下面的类,首先要声明
Horse h = null; //声明一个类的变量(除了八种基本数据类型以外,都是引用数据类型,包括数组)
// 创建一个Hoses类型的对象,实例化对象
h = new Horse()
// 有了对象, 我们就可以调用对象的属性和方法
h.name = "赤兔马";
h.age = 350;
// 调用对象的方法
h.run(); // 调用方法,方法就会被执行
h.eat();
// 匿名对象
new Horse().eat();//只能使用一次,用完后该对象就会被释放
h = null; // 把对象释放
// h.eat(); //当对象不存在时,调用该对象的属性和方法将报错(空指针)
}
}
// 定义一个类(类型)
class Horse{
// 在类中定义属性(特征)
String name;
int age;
public void run(){
System.out.println("我是"+name+",我"+age+"岁,我还可以跑")
}
public void eat(){
System.out.println("我吃的很多")
}
}
4、类与对象的内存详解
声明一个类的变量在栈中,栈内存一般存储变量名,地址,基本数据类型。当new关键字实例化以后,便会在堆内存申请内存空间,栈内存的地址则会指向堆内存的区域。注意name也是名字,还是会指向另外的地址,这里抽象一下表达。
当一个对象没有被引用,堆内存会被GC垃圾回收;
总结:
new关键字:表示向内存申请空间,也表示实例化一个对象,创建一个对象。
一个对象在内存中的大小,由该对象的所有属性所占的内存大小的总和。引用类型变量在32为系统上占4个字节,在64位系统上占8个字节。加上而外的对象隐性数据所占的大小。
相同的类型才可以赋值。
不同的引用,指向同一个对象,任何引用改变对象的值,其他引用都会反映出来。
编程时要注意的问题,在确定不使用对象时,要尽早释放对象:引用=null;
当一个堆中的对象没有被任何引用变量所指向时,该对象会被JVM的GC程序认为是垃圾对象,从而被回收。
三、面向对象封装性
1、封装性的概念
封装性是面向对象思想的三大特征之一。
封装性就是隐藏实现细节,仅对外提供访问接口。
封装有:
属性的封装、方法的封装、类的封装、组件的封装、模块化封装、系统级封装...
理解:如一台电脑的内部结构,由各种零配件组装而成,每个零配件又相互独立的提供功能
2、封装的好处
模块化、信息隐藏、代码重用、插件化易于调试、就有安全性
缺点:会影响执行效率;
/**
* 封装性
* 如果属性没有封装,那么在本类之外创建对象后,可以直接访问属性
* private 关键字:访问权限修饰符 私有的,只能在本类中访问;public 公有修饰符
*/
public class Test{
public static void main(String[] args){
Person p1 = new Person();
p1.name = "小小";
p1.age = 18;
p1.setName("yiyi");
p1.setAge(18);
System.out.println(p1.getName());
}
}
//封装之前
class Person{
String name;
int age;
}
//封装之后:
class Person{
// 属性是成员变量
private String name;
private int age;
// 参数及方法内定义的变量是局部变量
// 对外提供一个为name属性设值的方法
public void setName(String name){
this.name = name;
}
// 对外提供一个获取name属性的方法
public String getName(){
return name;
}
public void setAge(int age){
this.age= age;
}
public int getAge(){
return age;
}
}
3、成员变量和局部变量
i、在类中的位置不同
成员变量:在类中定义
局部变量:在方法中定义或者方法的参数
ii、在内存中的位置不同
成员变量:在堆内存(成员变量属于对象,对象进堆内存)
局部变量:在栈内存(局部变量属于方法,方法进栈内存)
iii、生命周期不同
成员变量:随着对象的创建而存在,随着对象的销毁而消失
局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
iv、初始化值不同
成员变量:由默认初始化值,引用类型默认为null
局部变量:没有默认初始化值,必须定义,赋值,然后才能使用
注意:局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则。
4、构造方法
i、什么是构造方法?
构造方法就是类构造对象时调用的方法,用于对象的初始化工作
构造方法是实例化一个类的对象时,也就是new的时候,最先调用的方法。
ii、构造方法的定义
构造方法是在类中定义的,构造方法的定义格式:方法名称与类名称相同,无返回值类型的声明。
对象的实例化语法:
Dog dog = new Dog(); //new Dog 后面有个括号,带括号表示调用了方法,此时调用的方法就是构造方法了。
public class Test{
public static void main(String[] args){
Dog dog = new Dog();
Dog dog1 = new Dog("wang",5);
}
}
class Dog{
// 默认的构造方法
public Dog(){
System.out.println("构造方法")
}
public Dog(String name){
this.name = name;
System.out.println("带一个参数构造方法")
}
// 构造方法的重载
public Dog(String name, int age){
// this(name); //调用其他构造方法时,此语句必须在第一句,在构造方法相互调用时必须要有出口
this.name = name;
this.age = age;
System.out.println("带参数构造方法")
}
}
iii、构造方法小结
构造方法名称与类名相同,没有返回值声明(包括void);
构造方法用于初始化数据(属性);
每一个类中都会有一个默认的无参的构造方法;
如果类中有显示的构造方法,那么默认构造方法将无效;
如果有显示的构造方法,还想保留默认构造方法,需要显示的写出来;
构造方法可以有多个,但参数不一样,称为构造方法的重载;
在构造方法中调用另一个构造方法,使用this(...),该句代码必须在第一句。
构造方法之间的调用,必须要有出口;
给对象初始化数据可以使用构造方法或setter方法,通常情况下,两者都会保留;
一个好的编程习惯是要保留默认的构造方法(为了方便一些框架代码使用反射来创建对象);
private Dog(){},构造方法私有化,当我们的需求是为了保证该类只有一个对象时。
什么时候一个类只需要一个对象?比如:工具类(没有属性,只有行为)并且该工具对象被频繁使用,权衡只用一个对象与产生多个对象的内存使用,来确定该类是否要定义为只需要一个对象。
四、this关键字、值传递与引用传递
1、this关键字
在java中,this关键字是一个重要的概念,使用this可以完成下面的操作:
调用类中的属性
调用类中的方法或构造方法
表示当前对象
public class Test{
public static void main(String[] args){
Cat cat = new Cat();
cat.setName("小白");// cat调用了方法,所以cat就是当前对象
cat.setAge(2);
cat.eat();
}
}
class Cat{
private String name;
private int age;
public void setName(String name){ //name=小白
this.name = name; // this代表当前对象 this表示cat,谁调用这个方法谁就是当前对象
}
public void getName(){
return name;
}
public void setAge(int age){
this.age= age;
}
public void getAge(){
return age;
}
public void eat(){
// 在方法中使用this调用类中其他方法,this可以省略,this前可以使用当前类名.this
System.out.println("我是"+Cat.this.getName()+",我爱吃鱼")
System.out.println("我是"+this.name+",我爱吃鱼")
}
}
2、值传递
上述代码输出的结果为10。为什么呢?
3、引用传递
输出结果为5,为什么呢?
这就是引用传递,变量存的是地址。
4、String类型传递
输出结果为小飞,为什么呢? 因为字符串本身就是一个对象。
输出结果为备备,
name在堆中存储的还是一个地址,指向另一块内存数据,下面这个p表示method方法中的p,然后调用name,重新赋值,这将改变name的地址,指向另一块内存数据,之前的"飞飞"变为垃圾对象。