第六章:面向对象基础
- 面向对象和面向过程的区别:
-
抽象的目的:将复杂的问题简单化
-
面向过程的抽象: 将几个有区别的物体的共同性质或特性,形象地抽取出来或孤立地进行考虑的行动或过程
-
面向对象的抽象:
- 从事物中舍弃个别的非本质特征,抽取共同的本质特征
- 只考虑与问题域相关的信息,而忽略与问题域不相关的部分
-
面向对象思想:面向对象编程思想实际上就是一种运用对象、类、继承、封装、聚合、关联、消息、多态性等概念来构造系统的软件开发方法
面向对象的分析(OOA,Object Oriented Analysis)
面向对象的设计(OOD,Object Oriented Design)
面向对象的编程实现(OOP,Object Oriented Programming) -
面向对象概念
- 对象:是系统中用来描述客观事物的一个实体
- 类是一组具有相同属性和行为的对象的抽象,类的作用是用来创建对象,对象是类的一个实例
/** * 商品类 * @author Administrator * 类和对象的关系:类是对象的模板,类就是用来产生对象的,对象就是类的具体实例 * */ public class Product { /** * 将商品公有的特征抽取出来声明属性(成员变量) * 成员变量定义在类中 * 每个的对象都拥有这些属性,只是对应的值不一样,称为成员变量 */ //商品编号 int pid; //名称 String pname; //价格 int pic; //数量 int pnum; //商品描述 String pdis; //成员方法 public void queryProduct() { System.out.println("查询商品信息"); } //成员方法 public boolean updateProduct(int pid) { System.out.println("修改商品信息"); return false; } public static void main(String[] args) { //创建一个商品对象 Product p1=new Product(); //访问属性:使用“.”运算符访问属性和方法 System.out.println(p1.pdis);//null System.out.println(p1.pnum);//0 //属性赋值:值的数据类型要和属性的数据类型一致 p1.pid=1; p1.pname="欧拉黑猫"; p1.pic=9; p1.pnum=1000; p1.pdis="纯电动车新能源汽车代步神器 一元试驾 订金"; p1.queryProduct(); System.out.println(p1.pname);//欧拉黑猫 Product p2=new Product(); p2.pname="长城"; p2.queryProduct(); System.out.println(p2.pname);//长城 Teacher t=new Teacher(); t.teaching(); }
-
- 成员变量和局部变量的区别
/**
* 教师类
* @author Administrator
* 变量必须初始化之后才能使用
*
* 局部变量:
* 声明在方法体中或者语句块中,作用域范围在声明的语句块中
*
* 成员变量:属于对象的
* 声明在类中,作用域范围是整个类
*
* 属性可以和局部变量同名,使用关键字this进行区分
成员方法可以直接调用成员变量和成员方法
*
*/
public class Teacher {
//成员变量
int age;
String name;
String sex;
int sal;
public void teaching() {
int x=20;
int sal=30;
System.out.println("成员方法teaching()"+tid);
System.out.println("成员方法teaching()"+sal);
//this:表示的是当前实例化对象,你可以看成是对象的引用
System.out.println("成员方法teaching()"+this.sal);
}
public void eat() {
System.out.println("成员方法eat()"+name);
}
int tid;
public static void main(String[] args) {
Teacher t1=new Teacher();
t1.tid=1;
t1.name="张德帅";
t1.sal=100;
// t1.eat();
t1.teaching();
Teacher t2=new Teacher();
t2.tid=2;
t2.name="张德美";
t2.sal=200;
// t2.eat();
t2.teaching();
// System.out.println(t1.name);
// System.out.println(t2.name);
//
}
- 对象的内存
/**
* 变量必须初始化之后才能使用
* @author Administrator
* 成员方法必须初始化之后才能使用
* 属性有默认值,因此可以不用赋值就可以使用
* 引用对象:默认为null int:0 double:0.0 boolean:false
* */
public class Teacher {
//成员变量
int age;
String name;
String sex;
int sal;
int tid;
public void teaching() {
eat();
System.out.println("成员方法teaching()"+name);
}
public void eat() {
System.out.println("成员方法eat()"+name);
}
public static void main(String[] args) {
int x=30;
Teacher t1=new Teacher();
System.out.println(t1);//@7852e922
System.out.println(t1.age);//0
System.out.println(t1.name);//null
t1.name="zhangsan";
System.out.println(t1.name);//zhangsan
Teacher t2=new Teacher();
System.out.println(t2);//@4e25154f
System.out.println(t2.age);//0
}
}
- 使用对象时注意的问题
//成员变量
String name;
int age;
//成员方法
public void getName() {
}
public void setName() {
getName();
}
public static void main(String[] args) {
/**
* ①在静态方法和其他类中使用时:成员变量和成员方法必须实例化之后才能调用
* ②什么是实例化:就是创建对象,通过new来创建一个对象
* ③怎么调用属性和成员方法:引用.方法名;引用.属性
* ④什么是引用:引用在java中就是地址的同义词
*
*/
Studnet s1=new Studnet();//创建了一个对象
new Studnet();//创建了一个对象
new Studnet().setName();
}
- 垃圾回收机制
/**
* 垃圾回收:只会回收堆内存的对象
* 垃圾回收机制:当内存中的对象过多是,垃圾回收线程会自动帮我们回收垃圾
* 当一个对象变成垃圾时,jvm会自动执行垃圾回收--finalize()
* 垃圾回收线程的优先级非常非常低
*
* 什么时候对象会变成垃圾?
* 当没有引用指向时,该对象就会变成垃圾
* 匿名对象
*
*
* @author Administrator
*
*/
public class Person {
public void getName() {
System.out.println("我是一万行代码");
System.out.println("haha");
}
//main:主线程
public static void main(String[] args) {
Person p=new Person();
p.getName();
p=null;
//匿名对象:作用--节省内存:当只想对对象执行一次操作时可以声明成匿名对象
new Person().getName();
System.out.println("我是一万行代码");
//超出对象的生命周期
for(int i=0;i<10;i++) {
Person p1=new Person();
}
//提升变量的生命周期
Person p2=null;
for(int i=0;i<10;i++) {
p2=new Person();
}
p2.getName();
}
-
垃圾回收算法:
- 复制算法
- 标记算法
- gc算法(*):将新生代(8:1:1)进行分割
- 8:存放新建的对象–Eden
- 1:1:两个Survivor
-
构造方法(构造器)
/**
* 特别强调:1、构造的作用:初始化对象的--成员变量、成员方法 2、方法和变量必须初始化之后才能使用
* ①构造器也称为构造方法
* ②语法:方法名和类名相同,没有返回值也没有void
* ③无参构造器的作用:初始化对象,给所有的成员变量赋默认值
* ④new 构造方法():new:内存空间分配符 完成对象实例化的同时完成了对象的初始化
* ⑤构造方法可以重载
* ⑥当没有提供构造方法时,编译器会默认提供一个无参的构造方法
* ⑦当一个类中有了有参的构造方法,编译器就不会再提供无参的构造方法,一般我们提供有参的构造方法的同时会提供一个无参的构造方法
* ⑧有参构造器的作用:初始化对象,
*
*
* @author Administrator
*
*/
public class Teacher {
int age;
String name;
double sal;
public Teacher() {
System.out.println("无参的构造方法");
}
public Teacher(int age) {
System.out.println("有参的构造方法"+age);
}
public Teacher(int age,String name,double sal) {
this.age=age;
this.name=name;
this.sal=sal;
System.out.println("有参的构造方法"+age);
}
public String getResult() {
return "age:"+this.age+" name:"+this.name+" sal:"+this.sal;
}
public static void main(String[] args) {
Teacher t1=new Teacher();
System.out.println(t1.getResult());
t1.age=10;
t1.name="zhangsan";
t1.sal=80;
System.out.println(t1.getResult());
// System.out.println(t1.getResult());
// System.out.println(t1.age);
// Teacher t2=new Teacher(10);
// System.out.println(t2.age);
Teacher t2=new Teacher(10,"zhangsan",80);
}
- java中包的使用
- 包允许将类组合成较小的单元
- 有助于避免命名冲突 :在同一个包中不能有同名的类
- 包允许在更广的范围内保护类、数据和方
- 注意:
- 在java中位于包中的类,在文件系统中的存放位置,必须有与包名层次相对应的目录结构
- package语句作为java源文件的第一条语句
- 每个源文件只能声明一个包:只能有一条package语句
- 如果没有package语句,则默认为无名包
- 位于同一包中的类可以直接访问并使用
- 使用不用包中的类时需要导包:import 包名.类名,java.lang是java默认包,java.lang不需要导入,编译器会自动导入java.lang包
- 导包:package像是我们的姓,而class名称就像是我们的名字 。
- 如果本包中的类名和其他包中的类名相同时,使用时默认调用本包中的类,如果想使用其他包中的同名的类,实例化时指定包名.类名,例如: 构造器.TestThree t2=new 构造器.TestThree();
- static关键字
/**
* static:静态关键字
* 注意:
* static不能修饰局部变量只能修饰属性
* 成员变量必须实例化之后才能通过引用.变量名 调用
* 成员方法可以直接调用成员方法和成员变量:在成员方法被其他类调用时一定是完成对象的初始化
* 修饰:
* 属性:static修饰的变量称为静态变量(类变量)
* 方法:static关键字修饰的方法称为静态方法(类方法)
* 代码块:static修饰的代码块称为静态代码块
*
* 静态方法和静态变量的访问:
* 对象实例化之后通过 引用.静态方法、引用.静态变量
* 类名.方法名、类名.静态变量(推荐)
* @author Administrator
* 结论:
* 1、静态变量和静态方法所有对象共享
* 2、静态资源在类加载的时候就完成了初始化,而非静态资源(成员变量和成员方法)是在实例化的
* 同时完成初始化工作
* 3、类加载一定是在对象实例化之前的,而且类加载只进行一次
* 4、静态方法不能直接访问成员方法和成员变量,成员方法可以直接访问静态方法和静态变量,静态方法能直接访问静态变量和方法
* 5、静态方法中不能使用this和super关键字
*/
public class Teacher {
//成员变量
int age;
//静态变量(类变量)
static int sex;
//成员方法
public void getAge() {
getSex();
System.out.println("成员方法getAge"+sex);
}
//成员方法
public void getAge1() {
getAge();
System.out.println("成员方法getAge1"+age);
}
//静态方法
public static void getSex() {
// System.out.println(this.age);
// getAge1();not
System.out.println("静态方法"+sex);
}
public static void main(String[] args) {
Teacher.getSex();
Teacher t=new Teacher();
t.getAge();
// Teacher t1=new Teacher();
// t1.age=20;
// t1.sex=2;
// Teacher.sex=3;
// System.out.println("age:"+t1.age);
// System.out.println("sex:"+t1.sex);//3
//
// Teacher t2=new Teacher();
// t2.age=18;
// System.out.println("age:"+t2.age);
// System.out.println("sex:"+t2.sex);//3
//
// Student s=new Student();
}
// public static void main(String[] args) {
// Teacher t=new Teacher();
t.getAge1();
// //静态方法的调用
// t.getSex();//静态方法
// System.out.println(t.sex);//0
//
// Teacher.getSex();
// System.out.println(Teacher.sex);
t.age=20;
System.out.println(t.age);//20
System.out.println(sex);//0
//
// }
- this()和this关键字
/**
* this 当前实例化对象;
* this(参数列表):指的是构造方法
* *:对象初始化只进行一次,this(参数列表)只能在构造其中被调用
* ①this(参数列表)必须放在构造器第一行
* ②一个构造器中只能调用一个this(参数列表)
* ③this(参数列表):通过传入的参数判断调用的是哪一个构造器
* @author Administrator
*
*/
public class Student {
String name;
int age;
// public Student() {
// System.out.println("无参的构造方法");
// }
public Student() {
// this();
// this("lisi",20);
// this("zhansan");
System.out.println("无参的构造方法");
}
public Student(String name) {
this.name=name;
}
public void getName() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
System.out.println("有参的构造方法");
}
public static void main(String[] args) {
Student s1=new Student();
// System.out.println(s1.age);//0 在没有调用this()之前;
System.out.println(s1.age);//20 在没有调用this()之后;
Student s2=new Student("zhangsan",10);
System.out.println(s2.age);
}
- 构造代码块和静态代码块
/**
* 构造代码块(成员代码块):
* {
* 完成对象初始化工作
* }
*
* 对象实例化过程:构造代码块--构造方法
* 编译器会自动将构造代码块放在构造器第一行
* @author Administrator
*
*/
public class Person {
int age;
String name;
public Person() {
// {
// System.out.println("构造代码块");
// }
System.out.println("构造方法");
}
public Person(int age, String name) {
this.age = age;
this.name = name;
}
{
this.age=20;
this.name="张三";
System.out.println("构造代码块");
}
// {
// this.age=0;
// this.name=null;
// System.out.println("构造代码块");
// }
public static void main(String[] args) {
Person p=new Person();
System.out.println(p.age);
}
/**
* 静态代码块:
* static{
* 完成静态资源初始化
* }
* @author Administrator
*
* 静态代码块执行一次而可以实例化多个对象--类加载一次可以实例化多个对象
* 类加载只进行一次
*
* 对象实例化过程:先类加载--初始化(实例化)
* */
public class Order {
int age;
static int sxe;
public Order() {
System.out.println("Order构造方法");
}
static {
sxe=0;
System.out.println("Order静态代码块");
}
public static void main(String[] args) {
Order o1=new Order();
// Order o2=new Order();
Student s1=new Student();
}
- 类加载的过程
public class Person {
int age;
static int sex=20;
// static Student s=new Student();
public Person() {
System.out.println("构造方法");
}
static {
System.out.println("静态代码块");
}
public static void main(String[] args) {
Person p=new Person();
Person p1=new Person();
}
- 单例模式
- 保证一个类在内存中只有一个实例(对象)
- 作用:节省内存
- 注意:使用单例模式的类,尽量不要在类中声明成员变量,声明也是声明常量,避免并发访问出现数据不一致的问题
/**
* 懒汉式:
* 实现单例模式的规则:
* ①提供一个私有构造器
* ②提供私有的、静态的自身属性的静态变量
* ③提供一个返回自身的静态公有方法
*
*
* @author Administrator
*
*/
public class Student_lazy{
private Student_lazy() {
System.out.println("实例化了");
}
private static Student_lazy student_lazy;
public static Student_lazy getStudentInstance_lazy() {
if(student_lazy==null) {
student_lazy=new Student_lazy();
}
return student_lazy;
}
public static void main(String[] args) {
System.out.println(student_lazy);
}
- 测试单例
public static void main(String[] args) {
// Teacher t1=new Teacher();
// t1.getResult();
// Teacher t2=new Teacher();
// t2.getResult();
// Teacher t3=new Teacher();
// Teacher t4=new Teacher();
// Teacher t5=new Teacher();
// Teacher t6=new Teacher();
// Teacher t7=new Teacher();
// Student_lazy s1=new Student_lazy();
Student_lazy s1=Student_lazy.getStudentInstance_lazy();
System.out.println(s1);//@7852e922
Student_lazy s2=Student_lazy.getStudentInstance_lazy();
System.out.println(s2);//@7852e922
// == 比较两个引用数据类型变量时比较的是地址
System.out.println(s1==s2);
Student_hungry s3= Student_hungry.getStudentInstance_hungry();
System.out.println(s3.age);
Student_hungry s4= Student_hungry.getStudentInstance_hungry();
System.out.println(s4.age);
System.out.println(s3==s4);
}