Java基础:Day_06 类、构造器和面向对象

一、对象与类

1.对象与类的关系
对象:对象是人们进行研究任何事物,一切事物都可认为是对象。对象具有状态和行为。
类:具有相同特性(状态)和行为(功能)的对象的抽象就是类。

一句话:对象的类的个性,类是对象的共性。

在面向对象编程里,我们肯定是先有类的。
如果没有类,对象就没法实例化。对象是类的实例,类是对象的模板。如下图,我们可以在类中找到对象的共性,如姓名年龄,以及他们的行为,但是对象是个例。在这里插入图片描述
那么我们可以在Java中这样写一个类:

//人类
class    Person
{
      String  name;
      int        age;
      int        height;
      int        weight;

       void  sing(){}
       void    dance(){}
}
//但是当我们要创建一个象这样特殊的“类”,对其进行实例化的时候,这个时候它就叫做对象了。

2.对象和类的创建

1):根据类来创建对象的语法:
类名 变量 = new 类名();
2):给字段设置值:
对象变量.字段名 = 该类型的值;
3):获取字段的值:
该字段类型 变量 = 对象变量.字段值;
4):通过对象调用方法.
对象变量.方法(实参);
实例如下:

class ServantDemo
{
	String name;
	int		age;

	void shop()
	{
		System.out.println("Shoping...");
	}
	void wash()
	{
		System.out.println("Washing...");
	}
}

class Demo
{
	public static void main(String[] args)
	{
		ServantDemo Wang = new ServantDemo();//实例化该类,创建对象Wang

		Wang.name = "Wang Xiaoming";		 //为对象Wang赋值
		System.out.println(Wang.name);
		Wang.age  = 23;						 //为对象Wang赋值
		System.out.println(Wang.age);
		Wang.shop();						 //调用其中的方法

		System.out.println("-------------------------");

		ServantDemo Liu = new ServantDemo();
		Liu.name = "Liu Cixin";
		Liu.age  = 56;
		
		System.out.println(Liu.name);	//输出Liu Cixin
		Liu = Wang;
		System.out.println(Liu.name);	//输出Wang Xiaoming
		Wang = null;
		System.out.println(Wang.name);	//Exception in thread "main" java.lang.NullPointerException

	}
}

二、构造器的使用
假如我们想在教务系统中创建一个学生对象的时候,代码如下:

Student s1  = new Student();//特别像在调用一个方法名称为Student的无参数方法.

我们把这种特殊的方法,称之为构造方法,构造器(构造函数/构造子:Constructor),但是我们发现在Student类中,却找不到该构造方法,却又没有报错。编译器在编译源文件的时候,会创建一个缺省的构造器。

构造器的作用:
1):创建对象,凡是必须和 new 一起使用。
2):完成对象的初始化操作。
构造器的特点:
1):构造器的名称和当前所在类的名称相同.
如果构造器名称叫XXX, new XXX();你看出来创建的是什么类型的对象吗?
2):禁止定义返回类型,千万不要使用void作为返回类型. void Student(){}这是普通方法。
3):在构造器中,不需要使用return。 其实构造器是有返回值的,返回的是当前创建对象的引用。

编译器创建的默认构造器的特点:
1):符合构造器特点.
2):无参数的.
3):无方法体.
4):如果类A没有使用public修饰,则编译器创建的构造器也没有public修饰.
使用了public修饰,则编译器创建的构造器也使用public修饰.

在这里插入图片描述
构造器:如果我们没有显示提供构造器,则编译器在编译时创建一个缺省的构造器。但是,如果我们显示定义了一个构造器,则编译器不再创建默认构造器。
推论:某一个类,至少存在一个构造器。

没有使用自定义构造器如下:

class PersonDemo
{
	String name = null;
	
	//Person(String n)//自定义构造器
	//{
	//	name = n;	//把n作为参数赋值给name。
	//}
}

class Demo
{
	public static void main(String[] args)
	{
		//创建对象:其实的调用构造器
		PersonDemo p1 = new PersonDemo();
		p1.name = "Will"; 
		System.out.println(p1.name);
		//强行使用会有:
		// 错误: 无法将类 PersonDemo中的构造器 PersonDemo应用到给定类型;
	}
}

使用了自定义构造器如下:

class PersonDemo
{
	String name = null;
	PersonDemo(String n)//自定义构造器
	{
		name = n;	//把n作为参数赋值给name。
	}
}

class Demo
{
	public static void main(String[] args)
	{
		//创建对象:其实的调用构造器
		PersonDemo p1 = new PersonDemo("will");
		System.out.println(p1.name);
	}
}

可以看到我们自定义构造器的效果。
当然,和方法一样,构造器在称为构造方法的同时,依然拥有方法的重载。

三、static关键字

更多static的内容看这个

当我们创建“人”这个对象都有name和age两个状态,但是不同对象的name的值和age的值是不一样的。也就是说,不同对象的name和age是不一样的。
但是在生活中有些东西不是属于某一个具体对象的,而是属于整个事物的类型,比如:全世界人的总数,人类的毁灭的行为,应该属于人类,而不属于某一个人。
状态和行为应该有对象和类型之分.
有的状态和行为应该属于对象,不同的对象,状态和行为可以不一样。
有的状态和行为应该属于类型,不属于对象。
问题:现在如何表示人类毁灭这个行为(destory)。
要解决该问题,得学习static修饰符。

关于修饰符(形容词),来看几个案例。
晚上11点,班长在写代码,遇到一个bug,班长解决问题后,睡觉去了。
晚上11点,班长漫不经心地在写代码,遇到一个很简单的bug,班长稀里糊涂解决问题后,满不在乎地睡觉去了。
晚上11点,帅气的班长认认真真地在写代码,遇到一个超难的bug,班长呕心沥血解决问题后,眉开眼笑地睡觉去了。
我们可以看到修饰符是需要对对象进行修饰的。

static修饰符表示静态的,可修饰字段、方法、内部类。
其修饰的成员属于类,也就是说static修饰的资源属于类级别,而不是对象级别。
static的真正作用:用来区别字段,方法,内部类,初始化代码块是属于对象还是属于类本身。

static修饰符的特点:
1.static修饰的成员(字段/方法),随着所在类的加载而加载。当JVM把字节码加载进入JVM时,static修饰的成员已经在内存当中。(static成员会先与JVM)

2.优先于对象的存在
对象时我们通过new关键字创建出来的

3.static修饰的成员被该类型的所有对象所共享。根据该类创建出来的任何对象,都可以访问static成员。。表面上通过对象去访问static成员,其本质依然是使用类名访问,
和对象没有任何关系。

4.因为static修饰的成员不属于对象,所以可以直接使用类名访问static成员。

成员和实例成员的访问 :
类中的成员:字段,方法,内部类.
类成员: 使用static修饰的成员.
实例成员: 没有使用static修饰的成员.

类成员只能访问类成员,实例成员只能访问实例成员.

类成员,直接属于类, 可以通过类来访问static字段和static方法.
实例成员,只属于对象, 通过对象来访问非static字段和非static方法.
(对象其实可以访问类成员,但是底层依然使用类名访问的.)
在static方法中,只能调用static成员。

非static方法,可以访问静态成员,也可以访问实例成员。

//Demo.java:7: 错误: 无法从静态上下文中引用非静态 变量 index
class Demo
{
	int index = 17;//index没有static修饰,属于对象,只能用对象访问。
	public static void main(String[] args)
	{
		System.out.println(index);
	}
}

但是我们将代码改为:

class Demo
{
	int index = 17;
	public static void main(String[] args)
	{
		Demo d = new Demo();
		System.out.println(d.index);
		//System.out.println(new Demo().index);上一句也可以这么写
		//里面包含了一个匿名内部类。
	}
}

当然如果加上了static:

class Demo
{
	static int index = 17;
	public static void main(String[] args)
	{
		System.out.println(index);
	}
}

案例2:

class MyObjectDemo
{
	private static String str1 = "String_1";
	private	static String str2 = "String_2";

	public void print_1()
	{
		System.out.println(str1);
		System.out.println(str2);
	}

	public static void print_2()
	{
		System.out.println(str1);
		System.out.println(str2);
	}
}

class Demo
{
	public static void main(String[] args)
	{
		MyObjectDemo.print_2();//static方法直接用类名调用,也可以是new了之后,用obj调用
		//但是print_1不行,因为他没有用static修饰
	}
}

但是,假如将MyObjectDemo类中的str2的static去掉之后。

class MyObjectDemo
{
	private static String str1 = "String_1";
	private	 String str2 = "String_2";

	public void print_1()
	{
		System.out.println(str1);
		System.out.println(str2);
	}

	public static void print_2()
	{
		System.out.println(str1);
		System.out.println(str2);//此处将无法引用str2
	}
}

class Demo
{
	public static void main(String[] args)
	{
		MyObjectDemo.print_2();
	}
}

对于方法还有:

class MyObjectDemo
{
	private static String str1 = "String_1";
	private	static String str2 = "String_2";

	public void print_1()
	{
		System.out.println(str1);
		System.out.println(str2);
		print_2(); //非static可以访问static
	}

	public static void print_2()
	{
		System.out.println(str1);
		System.out.println(str2);
		print_1();	//static不能访问非static
	}
}

class Demo
{
	public static void main(String[] args)
	{
		//MyObjectDemo obj = new MyObjectDemo();
		MyObjectDemo.print_2();
	}
}

总结以上:
1.对于static方法:static方法可以只能调用static成员,而非static无要求。如static修饰的Print_2只能调用被static修饰的str1,不能调用未经static修饰的str2。(自家人只和自家人玩)
2.static变量:static变量被所有的对象所共享(诞生时就产生的个人“标志”),在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非static变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
static成员变量的初始化顺序按照定义的顺序进行初始化。
3.static代码块:形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。(static代码块后面再说)

什么时候定义成static的字段和方法:

如果这一个状态/行为属于整个事物(类),就直接使用static修饰被所有对象所共享。

如果不使用static修饰,则这些方法属于该类的对象,我们得先创建对象再调用方法,在开发中工具对象只需要一份即可,可能创建N个对象,此时我们往往把该类设计为单例的.,但是还是有点麻烦。

一般的,在开发中设计工具方法,为了调用简单,我们使用static修饰。
因为加了static就可以使用类名调用 ,如果没有加static那么只能只用对象名称调用。

类成员的使用

利处:对对象的共享数据进行单独空间的存储,节省空间,没有必要每一个对象中都存储一份,可以直接被类名调用。
弊端:生命周期过长。

猜你喜欢

转载自blog.csdn.net/PandaNotPan/article/details/89221811