JAVA面向对象(上)

1.面向对象基本概念

什么是面向对象:
面向对象是一种编程思想.
面向对象是一种思考问题的思维方式.

二.建立面向对象思维方式
先整体,再局部(搭房子)
先抽象,再具体
能做什么,再怎么做

三.如何学习面向对象:
掌握一门面向对象语言的语法
熟悉面向对象的设计原则
熟悉面向对象的设计模式(23种设计模式,常用的是10种)

2.类与对象

什么是类?

类是:分类,类别.
通过分类,我们可以区别不同的事物种类,在日常生活中,我们常常这样做.
所以,类是一组具有相同特性(属性)与行为(方法)的事物集合.

类与对象的关系:
类表示一个共性的产物,是一个综合的特征,而对象,是一个个性的产物,是一个个体的特征.
类由属性和方法组成:
属性:就相当于一个个的特征.
方法:就相当于人的一个个行为,例如:说话,吃饭,唱歌,睡觉

3.类和对象的定义格式

注意:类是类别,分类的意思,所以类不是一个具体的事物,类代表一类事物,类的结果规则需要记住.

在JAVA中可以使用以下的语句定义一个类:
class 类名称{
属性名称;
返回值类型 方法名称(){}
}

对象的定义:
一个类要想进行真正的进行操作,则必须依靠对象,对象的定义格式如下:
类名称 对象名称=new 类名称();
按照以上格式就可以产生对象了.

如果要想访问类中的属性或方法 (方法的定义)
则可以依靠以下的语法形式:
访问类中属性:
对象.属性;
调用类中的方法:
对象.方法();

/**
	2022-2-18
	面向过程,以步骤为单位,U一步一步完成某一个具体事情
	面向对象,以对象为单位,通过调度组合不同的对象来完成某一个事情
	
*/
public class Test26{
	public static void main(String[] args){
		
		Horse h=null;//声明一个类的变量(除了八种基本数据类型以外,都是引用数据类型,包括数组)
		
		//实例化对象,创建一个Horse类型的对象
		h=new Horse();
		//有了对象,我们就可以调用对象的属性和方法
		h.name="赤兔马";
		h.age=13;
		
		h.run();//调用方法那么方法就会被执行
		
		//匿名对象,只能使用一次,用完后,该对象就会被释放
		new Horse().run();
		
		h=null;//把对象释放掉
		//当对象不存在时,调用该对象的属性和方法就会报错(空指针)
		//空指针错误(java.lang.NullPointerException)
		h.run();
	}
}

//自定义一个类(类型)
class Horse{
	//在类中定义属性(特征)
	String name;
	int age;
	public void run(){
		System.out.println("我是"+name+"\n年龄:"+age+"\n能力:日行千里!");
	}
	public void eat(){
		System.out.println("吃的食物:优良的马草!");
	}
}

4.对象内存分析

new关键字表示创建一个对象
new关键字表示实例化对象
new关键字表示申请内存空间

注意:如果使用一个没有申请内存空间的对象,回报空指针异常
java.lang.NullPointerException

类与对象小结

new关键字,表示向内存申请空间,也表示实例化一个对象,创建一个对象
一个对象在内存中的大小,由该对象的所有属性所占的内存大小的总和.引用类型变量在32位系统上占4个字节,在64位系统占8个字节,加上而外的对象隐形数据所占的大小.
相同的类型才可以赋值

不同的引用,指向同一个对象时,热河一个引用改变对象的值,其他引用都会反映出来.
编程时需要注意的问题,在确定不使用对象时,要尽早释放对象,引用null.

当一个堆中的对象没有被任何引用变量所指向时,该对象会被JVM的GC程序认为是垃圾对象,从而被回收.

5.封装性

封装性的概念
封装性是面向对象思想的三大特征之一.
封装就是隐藏实现细节,仅对外提供访问接口.
封装有:
属性的封装,方法的封装,类的封装,组建的封装,模块化封装,系统级封装…

封装的好处

模块化
信息隐藏
代码重用
插件化易于调试
具有安全性
封装缺点:
会影响执行效率

封装性
如果属性没有封装,那么在本类之外创建对象呢后,可以直接访问属性
private关键字:访问权限修饰符
public表示公有的,private表示是私有的,私有的属性或方法,只能在奔雷中访问
公有的属性和方法,可以被类外部的其他类直接进行访问

成员变量和局部变量

在类中的位置不同
成员变量:在类中定义
局部变量:在方法中定义或者方法的参数
在内存中的位置不同
成员变量:在堆内存(成员变量属于对象,对象进堆内存)
局部变量:在栈内存(局部变量属于方法,方法进栈内存)
声明周期不同
成员变量:随着对象创建而存在,随着对象的销毁而消失
局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
初始化值不同
成员变量:有默认初始值,引用类型默认是null
局部变量:没有默认初始值,必须定义,赋值,然后才能进行使用
注意:局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则.

/**
	2022-2-19
	封装性
	
*/
public class Test27{
	public static void main(String[] args){
		
		Person p=new Person();
		p.setName("萌萌");
		System.out.println("名字是:"+p.getName());
		
	}
}

//加上private就是进行封装了
class Person{
	//属性的封装
	private String name;//成员变量,在类中定义
	private int age;//成员变量
	
	//getter和setter
	//对外提供一个可以访问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 run(int len){
		int i;
		int m=len;//m也是局部变量
		System.out.println("我跑了"+m+"米");
		System.out.println("年龄是"+age);
	}
}

6.构造方法

什么是构造方法
构造方法就是类构造对象时调用的方法,用于对象的初始化工作
构造方法是实例化一个类的对象时,也就是new的时候,最先调用的方法.

构造方法的定义:
构造方法是在类中定义的,构造方法的定义格式:方法名称与类名称相同,无返回值类型的声明.
对象实例化语法:
Dog dog=new Dog();
//Dog后面有个括号,带括号表示调用了方法,此时调用的方法就是构造方法了

构造方法有别于普通方法,可以看做是一个特殊方法,是类在创建对象时自动调用的方法,可以为类的创建初始化属性值

构造方法小结

构造方法名称与类名相同,没有返回值声明(包括void)
构造方法用于初始化数据(属性)
每一个类中都会有一个默认的无参构造方法
如果类中显示的构造方法,那么默认构造方法将无效
如果有显示构造方法,还像保留默认构造方法,需要显示的写出来
构造方法可以有多个,但参数不一样,称为构造方法的重载
在构造方法中调用另一个构造方法,使用this(…),该句代码必须在第一句
构造方法之间的调用,必须要有出口
给对象初始化数据可以使用构造方法或setter方法,通常情况两者都会保留.

一个好的编程习惯是要保留默认的构造方法(为了方便一些框架代码使用反射来创建对象)
private Dog(),构造方法私有化,当我们的需求是为了保证该类只有一个对象时.
什么时候一个类只需要一个对象?比如,工具类(没有属性的类,只有行为)并且该工具对象被频繁使用,权衡只有一个对象与产生多个对象的内存使用,来确定该类是否要定义为只需要一个对象.

7.this关键字

在JAVA中,this关键字是一个重要的概念.使用this关键字可以完成一下的操作:
调用类中的属性
调用类中的方法或构造方法
表示当前对象:在方法被调用的过程中,哪个对象调用了方法,在方法内的this就表示谁
在方法中使用this调用类中的其他方法或属性,this可以省略,this前面可以使用当前的类名
注意:this表示当前对象本身,简单来说,哪个对象调用了this所在类中的任一方法或属性,this就代表是哪个对象

/**
	2022-2-19
	构造方法
*/
public class Test28{
	public static void main(String[] args){
		
		Dog dog=new Dog();
		Dog dog1=new Dog("汪汪",5);
	}
}


class Dog{
	//声明变量
	private String name;
	private int age;
	
	//构造方法
	public Dog(){
		System.out.println("构造方法执行了");
	}
	public Dog(String name){
		this.name=name;
		System.out.println("带一个参数的构造方法被执行了!");
	}
	public Dog(String name,int age){
		this(name);
		//调用其他构造方法时,此语句需要在第一句,在构造方法相互调用时必须要有出口
		this.age=age;
		System.out.println("带两个参数的构造方法被执行了!");
		//this(name);错误,必须先写this
	}
	
	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;
	}
	
}

8.值传递与引用传递

值传递和引用传递

引用传递的本质是传递内存空间地址,而非值本身,通过内存图充分理解栈内存和堆内存

9.对象的一对一关系

两个对象之间的一对一关系:
比如:一个英雄对一个兵器
代码如何表示?

/**
	2022-2-19
	两个对象之间的一对一关系:
	比如:一个英雄对一个兵器
	代码如何表示?
	双向一对一
	单向一对一
*/
public class Test29{
	public static void main(String[] args){
		
		Hero hero=new Hero("刘备",200);
		Weapon weapon=new Weapon("双锤",4);
		
		//把两个对象关联起来
		hero.setWeapon(weapon);
		weapon.setHero(hero);
		
		//通过英雄来获取他的信息
		String name=hero.getName();
		int age=hero.getAge();
		Weapon w=hero.getWeapon();
		System.out.println("我是"+name+",我是"+age+"岁,我的武器是:"+w.getName()+",排行"+w.getGrade()+"级");
		
	}
}

//英雄类
class Hero{
	//声明变量
	private String name;
	private int age;
	private Weapon weapon;
	
	public Hero(){
		
	}
	public Hero(String name,int age){
		this.name=name;
		this.age=age;
	}
	
	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 setWeapon(Weapon weapon){
		this.weapon=weapon;
	}
	
	public Weapon getWeapon(){
		return weapon;
	}
}


class Weapon{
	private String name;
	private int grade;
	private Hero hero;
	
	public Weapon(){}
	public Weapon(String name,int grade){
		this.name=name;
		this.grade=grade;
	}
	
	public void setName(String name){
		this.name=name;
	}
	
	public String getName(){
		return name;
	}
	
	public void setGrade(int grade){
		this.grade=grade;
	}
	
	public int getGrade(){
		return grade;
	}
	
	public void setHero(Hero hero){
		this.hero=hero;
	}
	
	public Hero getHero(){
		return hero;
	}
}

10.static关键字

static关键字的作用:

使用static关键字修饰一个属性
声明为static的变量实质上就是全局变量

2.使用static关键字修饰一个方法
通常,在一个类中定义一个方法为static,那就是说,无需本类的对象即可调用此方法

3.使用static关键字修饰一个类(内部类)

static使用总结

静态变量或方法不属于对象,依赖类
静态变量是全局变量,生命周期从类加载后一直到程序结束
静态变量只有存一份,在静态方法区存储
静态变量是本类所有对象共享一份
建议不要使用对象名去调用静态数据,直接使用类名调用
static修饰一个方法,那么该方法属于类,不属于对象,直接用类名调用
静态方法不能访问非静态属性和方法,只能访问静态

/**
	2022-2-19
	静态变量或方法不属于对象,依赖类
	静态变量是全局变量,生命周期从类加载后一直到程序结束
	静态变量只有存一份,在静态方法区存储
	静态变量是本类所有对象共享一份
	建议不要使用对象名去调用静态数据,直接使用类名调用
	static修饰一个方法,那么该方法属于类,不属于对象,直接用类名调用
	静态方法不能访问非静态属性和方法,只能访问静态

*/
public class Test30{
	public static void main(String[] args){
		
		Role liubei=new Role("刘备","蜀国");
		Role yunchang=new Role("云长");
		Role zhangfei=new Role("张飞");
		
		liubei.getInfo();
		yunchang.getInfo();
		zhangfei.getInfo();
		
		System.out.println("--------------------");
		System.out.println(liubei.country);
		System.out.println(yunchang.country);
		System.out.println(zhangfei.country);
		
		System.out.println("--------------------");
		liubei.country="唐朝";
		System.out.println(liubei.country);
		System.out.println(yunchang.country);
		System.out.println(zhangfei.country);
		
	}
}


class Role{
	private String name;
	static String country;//静态全局变量
	
	public Role(){}
	public Role(String name){
		this.name=name;
	}
	public Role(String name,String country){
		this.name=name;
		Role.country=country;
	}
	
	public void setName(String name){
		this.name=name;
	}
	
	public String getName(){
		return name;
	}
	
	//静态方法不能访问非静态的数据
	public static void setCountry(String country){
		Role.country=country;
	}
	
	public void getInfo(){
		System.out.println("我的名字是:"+name+",国家是"+Role.country);
	}
}

声明为static的方法有以下几限制:

它们仅能调用其他的static方法.
它们只能访问static数据
它们不能以任何方式引用this或super.

什么时候使用static?

所有对象共同的属性或方法,那么我们应该定义为静态的.

11.main方法分析

main方法分析
主方法:
public static void main(String[] args){
代码块
}

public:公有的,最大的访问权限
static:静态的,无需创建对象
void:表示没有返回值,无需向JVM返回结果
main:方法名,固定的方法名
String[] args:表示参数为字符串数组,可以在调用方法时传入参数

12.代码块

普通代码块
在方法中写的代码块

构造块
在类中定义的代码块,在创建对象时被调用,优于构造方法被调用

静态代码块
在类中使用static声明的代码块称为静态代码块
在第一次使用的时候被调用(创建对象),只会执行一次,优于构造块执行
我们在项目开发中,通常会使用静态代码块来初始化只调用一次的数据.

比如说:

重点:
会使用的顺序是静态代码块,普通代码块,同步代码块,构造代码块!

理解代码块的作用以及实初始化的过程,注意,静态代码块可在未来开发中用来启动项目时需要初始化数据的工作

13.单例设计模式

注意:单例模式的思想在于保证工具类仅有一个实例,以节省工具类在频繁使用时不断创建对象消耗内存的场景,也是面试中常见的笔试题

单例设计模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点.

构造方法私有化
声明一个本类对象
给外部提供一个静态方法获取对象实例

两种实现方式:

饿汉式:在第一次调用getInstance方法时,对象被创建,到程序结束后释放
懒汉式:在类被加载后,对象被创建,到程序结束后释放

/**
	2022-2-20
	
*/
public class Test32{
	public static void main(String[] args){
		
		//Singleton1 s=new Singleton1();错误
		Singleton1 s=Singleton1.getInstance();
		s.print();
		Singleton1 s1=Singleton1.getInstance();
		s1.print();
		System.out.println(s==s1);
		
		Singleton2 s2=Singleton2.getInstance();
		s2.print();
		Singleton2 s3=Singleton2.getInstance();
		s3.print();
		System.out.println(s2==s3);
		
	}
}

//饿汉式:占用内存的时间长,提高效率
class Singleton1{
	
	private Singleton1(){}
	private static Singleton1 s=new Singleton1();
	public static Singleton1 getInstance(){
		return s;
	}
	
	public void print(){
		System.out.println("饿汉式测试方法!");
	}
	
}

//懒汉式:占用内存时间短,效率稍低一点
//生命周期短一点
//在多线程访问时会有安全问题
class Singleton2{
	private Singleton2(){}
	private static Singleton2 s;
	
	public static Singleton2 getInstance(){
		if(s==null){
			s=new Singleton2();
		}
		
		return s;
	}
	
	public void print(){
		System.out.println("懒汉式测试方法!");
	}
	
}

在项目中为什么要使用单例,单例有什么好处?

1.在设计一些工具类的时候(通常工具类,只有功能方法,没有属性)
2.工具类可能会被频繁调用
好处:
目的是为了节省重复创建对象所带来的的内存消耗,从而提高效率

能不能使用构造方法私有化+静态方法来替代单例?

/**
	2022-2-20
	
*/
public class Test32{
	public static void main(String[] args){
		
		//Singleton1 s=new Singleton1();错误
		Singleton1 s=Singleton1.getInstance();
		s.print();
		Singleton1 s1=Singleton1.getInstance();
		s1.print();
		System.out.println(s==s1);
		
		Singleton2 s2=Singleton2.getInstance();
		s2.print();
		Singleton2 s3=Singleton2.getInstance();
		s3.print();
		System.out.println(s2==s3);
		
	}
}

//使用构造方法私有化,来实现工具类,比如Math
class Tools{
	
	private Tools(){}
	public static void print1(){
		
	}
	public static void print2(){
		
	}
}

//饿汉式:占用内存的时间长,提高效率
class Singleton1{
	
	private Singleton1(){}
	private static Singleton1 s=new Singleton1();
	public static Singleton1 getInstance(){
		return s;
	}
	
	public void print(){
		System.out.println("饿汉式测试方法!");
	}
	
}

//懒汉式:占用内存时间短,效率稍低一点
//生命周期短一点
//在多线程访问时会有安全问题
class Singleton2{
	private Singleton2(){}
	private static Singleton2 s;
	
	public static Singleton2 getInstance(){
		if(s==null){
			s=new Singleton2();
		}
		
		return s;
	}
	
	public void print(){
		System.out.println("懒汉式测试方法!");
	}
	
}

14.对象数组与管理

1.对象数组就是数组里的每个元素都是类的对象,赋值时先定义对象,然后讲对象直接赋给对象.
示例:
Chicken[] cs=new Chicken[10];
使用对象数组实现多个Chicken的管理.

/**
	2022-2-20
	对象数组管理案例
	动态数组:
	1.数组是一种线性数据结构
	2.数组不适合删除插入等操作,适合添加,查找,遍历
*/
import java.util.Arrays;
public class Test33{
	public static void main(String[] args){
		
		ChickenManger cm=new ChickenManger(5);
		cm.add(new Chicken(1,"小小",10));
		cm.add(new Chicken(2,"小二",9));
		cm.add(new Chicken(3,"小三",8));
		cm.add(new Chicken(4,"小四",7));
		cm.add(new Chicken(5,"小五",6));
		
		cm.add(new Chicken(6,"小六",5));
		System.out.println("现在数组的长度是:"+cm.length());
		
		System.out.println("-------------printAll------------");
		cm.printAll();
		
		System.out.println("------------find----------");
		Chicken c=cm.find(6);
		System.out.println(c.print());
		
		System.out.println("--------------update----------------");
		cm.update(new Chicken(1,"小王八",19));
		cm.printAll();
		
		System.out.println("-------------delete------------------");
		cm.delete(2);
		cm.printAll();
		
		
	}
}

//小鸡管理类
class ChickenManger{
	
	private Chicken[] cs=null;
	private int count=0;//记录当前数组元素的个数(下标)
	
	public ChickenManger(){}
	public ChickenManger(int size){
		if(size>0){
			cs=new Chicken[size];
		}
		else{
			cs=new Chicken[5];
		}
	}
	
	public int length(){
		return cs.length;
	}
	
	//添加,实现动态数组
	public void add(Chicken c){
		if(count>=cs.length){
			//数组已满,需要扩充
			
			//算法一:扩充原来的一半
			int newLen=cs.length*2;
			cs=Arrays.copyOf(cs,newLen);
			
			//算法二:扩充原来的一倍
		}
		cs[count]=c;
		count++;
	}
	//删除
	public void delete(int id){
		
		for(int i=0;i<count;i++){
			if(cs[i].getId()==id){
				//找到了要删除的对象,把该对象之后的对象向前移动一位
				for(int j=i;j<count-1;j++){
					cs[j]=cs[j+1];
				}
				//把最后一个对象赋值为空
				cs[count-1]=null;
				count--;//下标减一
				break;
			}
		}
	}
	//更新
	public void update(Chicken c){
		Chicken temp=find(c.getId());
		if(temp!=null){
			temp.setName(c.getName());
			temp.setAge(c.getAge());
		}
	}
	//查找
	public Chicken find(int id){
		for(int i=0;i<count;i++){
			if(cs[i].getId()==id){
				return cs[i];
			}
		}
		return null;
	}
	//输出所有
	public void printAll(){
		for(int i=0;i<count;i++){
			System.out.println(cs[i].print());
		}
	}
}

//小鸡类(数据对象)value object(vo)
class Chicken{
	
	private int id;
	private String name;
	private int age;
	
	public Chicken(){}
	public Chicken(int id,String name,int age){
		this.id=id;
		this.name=name;
		this.age=age;
	}
	
	public void setId(int id){
		this.id=id;
	}
	public int getId(){
		return id;
	}
	
	public void setName(String name){
		this.name=name;
	}
	public String getName(){
		return name;
	}
	
	public void setAge(int age){
		this.age=age;
	}
	public int getAge(){
		return age;
	}
	
	public String print(){
		return "小鸡ID是"+id+",小鸡的名字是"+name+",月份是"+age;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值