零基础学Java第五节(面向对象一)

华为2021年天线工程师笔试题目回忆总结(持续更新) 1. 判定长线和短线 所谓长线是指传输线的几何长度和线上传输电磁波的波长的比值(即电长度)大于或接近于1。反之称为短线。是相对于波长而言的。 1000m的传输线,对于频率为50hz(即波长为6000km)的交流电来说,仍远小于波长,应视为短线。长线和短线的区别还在于:长线为分布参数电路,而短线是集总参数电路。 2. 判定传输线的容性和感性 传输线上的输入阻抗具有以下特点: 1/4波长变换性:感性负载与容性负载变换,开路与短路变换; 1/2波长重复性:相距1/2波长的整数倍的两个点输入阻抗都相等。1/4开路传 阅读详情

优快云话题挑战赛第1期
活动详情地址:https://marketing.youkuaiyun.com/p/bb5081d88a77db8d6ef45bb7b6ef3d7f
参赛话题:Java学习记录
话题描述:零基础学习Java类与对象
————————————————
版权声明:本文为优快云博主「Code_ForYou」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

本篇文章是《零基础学Java》专栏的第五篇文章,文章采用通俗易懂的文字、图示及代码实战,从零基础开始带大家走上高薪之路!

类与对象

在哲学体系中,可以分为主体(subject)和客体(object),在面向对象的程序设计语言中,所有的要面对的事物都可以抽象为对象(object)。在面向对象的编程过程中,我们就是使用各种各样的对象相互协同动作来完成我们的程序功能。

在面向对象的语言中,所有使用中的对象都具有某种类型,这些类型之间也有层次关系,如同生物学中的门、纲、目、科、属、种一样,这种层次关系,我们可以用继承这个机制来完成。

Java语言为面向对象的语言,所有的对象都可以具有某些属性,以及具有某种行为功能。在Java语言中对象的属性用成员变量(域)描述,行为用方法描述。

类和对象之间的区别和联系就是,类是抽象的,它具有一类对象所有的属性和行为,相当于模板,对象是具体的,通过创建相应类的对象来完成相应的功能。我们在作面向对象的编程的时候,就是抽象出类的属性和行为,再创建具体的对象来完成功能。

Date类

定义

在JDK中,有一个用于描述日期的类:java.util.Date,它表示特定的瞬间,精确到毫秒。在这里我们自己定义一个简单的Date类,用来表示具有年、月、日的日期。我们先来看看如下定义怎么样?

public class Date{
	public int year;
	public int month;
	public int day;
}

在这段程序定义中,类定义为public,同时year、month、day也定义为public,它们是什么含义呢?

我们前面提到包这个概念,我们说,在同一个包中的类在功能上是相关的,但是在包内的这些类并非全部都可以被其他包中的类调用的,怎么区分呢?那些可以被包外使用的类,我们在定义的时候,在类名前加上public,而不能被包外使用的类,在定义的时候,不要加public。

year、month、day这些在类体中所定义的变量,我们称之为成员变量(域 field),那么成员变量前面的public的作用是说明这些变量是公开的,可以被以 对象.变量 这种形式调用,这称为成员变量的访问权限。比如本例:我们定义一个Date类型的变量d1,那么我们可以通过d1.year来使用d1这个对象中的year。在定义成员变量的时候,除了可以定义为public,还可以有protected、缺省(无权限修饰词)、private,它们的限制越来越严格,我们总结一下:

  • public:被public修饰的成员是完全公开的,可以被以任何合法的访问形式而访问
  • protected:被protected修饰的成员可以在定义它们的类中访问,也可被同一包中的其他类及其子类(该子类可以同其不在同一个包中)访问,但不能被其他包中的非子类访问
  • 缺省:指不使用权限修饰符。该类成员可以在定义它们的类中被访问,也可被其同一包中的其他类访问,但不能被其他包中的类访问,其子类如果与其不在同一个包,也是不能访问的。
  • private:只能在定义它们的类中访问,仅此而已。

在类中,我们不但可以定义成员变量,还可以定义成员方法,成员方法前面也可以有这四种权限控制,含义是一样的。但是大家千万不要以为在独立类的前面也可以有private、protected这两个修饰词,在类前只能有public或者没有,含义前面已述。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hTfq9VvZ-1652788721418)(https://cdn.jsdelivr.net/gh/yuan-more/cdnscope.png)]

关于public类和源程序文件的关系,我们在以前学习过,这里再重新提一下:

每个源代码文件中至少定义一个类,若有多个类,最多只有一个类定义为public,若有public类,则该源代码文件的前缀名字要同该类的类名完全一致,若没有public类,则源代码文件的前缀名可不与文件内的任何类一致。

测试

上面的Date类已经定义好了,我们怎么测试这个类呢?我们在这个类中定义main方法了吗?没有main方法的类,可以以 java 类名 这种方式在控制台中执行吗?显然不行,那怎么办呢?有两种方案,一种是我们给它定义一个main方法;另一种方案,再定义一个类,专门测试这个Date类。我们依次来看看。

添加main方法

我们在Date的定义中加入main方法,代码如下:

public class Date{
	public int year;
	public int month;
	public int day;

	public static void main(String[] args){
		year = 2016;
		month = 9;
		day = 5;
		System.out.println("year:" + year + " month:" + month + " day:" + day);
	}
}

编译…,怎么?又错了?[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GflB4MVJ-1652788721427)(https://cdn.jsdelivr.net/gh/yuan-more/cdnDate1.png)]
别慌,看看出错提示,都是无法从静态上下文中引用非静态 变量这样的提示,这是什么意思?我们看看main方法前面是不是有个修饰词static,我们前面提到凡static修饰的成员变量或者方法,都可以用 类名.成员 这种形式来访问。如果Date类在控制台中以 java Date这种命令形式来执行,我想请问,系统是创建了一个Date对象了,然后再执行这个对象中的main方法这种方式来执行的Date类吗?错,系统是直接找到Date.class这个类文件,把这个类调入内存,然后直接执行了main,这时在内存中并没有Date对象存在,这就是为什么main要定义为static,因为main是通过类来执行的,不是通过对象来执行的。

那上面的解释又同这个编译错误提示什么关系?我们看看 year、month、day前面有没有static这个修饰词?没有,这说明这些成员变量不能通过类名直接访问,必须通过创建类的对象,再通过对象来访问。而main在执行的时候,内存中并没有对象存在,那自然那些没有static修饰的成员就不能被访问,因为它们不存在,是不是这个逻辑?想明白了吗?还没有?再想想!

我们得出个能记住的结论,在static修饰的方法中,只能使用本类中那些static修饰的成员(包括成员变量、方法等),如果使用本类中非static的成员,也必须创建本类的对象,通过对象使用。好吧,不明白道理,就先把这个结论记着。

我们根据上面的结论,把测试代码再改改:

public class Date2{
	public int year;
	public int month;
	public int day;

	public static void main(String[] args){
		Date2 d1 = new Date2();
		d1.year = 2016;
		d1.month = 9;
		d1.day = 5;
		System.out.println("year:" + d1.year + " month:" + d1.month + " day:" + d1.day);
	}
}

编译…,OK,运行,通过,[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sRCqkzZP-1652788721432)(https://cdn.jsdelivr.net/gh/yuan-more/cdnDate2.png)]

那如果非静态方法中使用静态成员,可不可以呢?我们说可以,简单讲,这是因为类先于对象存在,静态成员依赖于类,非静态成员依赖于对象。

上面的程序中,我们给这几个成员变量分别给了值,如果不给值直接输出呢?我们试试:

public class Date3{
	public int year;
	public int month;
	public int day;

	public static void main(String[] args){
		Date3 d1 = new Date3();
		System.out.println("year:" + d1.year + " month:" + d1.month + " day:" + d1.day);
	}
}

编译,运行,结果:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4twpPWqI-1652788721435)(https://cdn.jsdelivr.net/gh/yuan-more/cdnDate3.png)] ,都是0。这里有个结论:成员变量如果没有显式初始化,其初始值为0值,或者相当于0值的值,比如引用变量,未显式初始化,其值为null,逻辑变量的未显式初始化的值为false。这里要注意,我们说的是成员变量,如果是局部变量,没有显式初始化就用,编译是通不过的。比如上面的代码,改为:

public class Date3{
	public int year;
	public int month;
	public int day;

	public static void main(String[] args){
		Date3 d1;//这里d1为局部变量,没有初始化
		System.out.println("year:" + d1.year + " month:" + d1.month + " day:" + d1.day);
	}
}

编译:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5z62hCJH-1652788721437)(https://cdn.jsdelivr.net/gh/yuan-more/cdnDate3_error.png)] 从编译提示,我们知道d1未初始化就用,这是不对的。

创建一个测试类

代码如下:

//本类放在Date.java文件中
public class Date{
	public int year;
	public int month;
	public int day;
}

//本类放在TestDate.java文件中
public class TestDate{
	public static void main(String[] args){
		Date d1 = new Date();
		d1.year = 2016;
		d1.month = 9;
		d1.day = 5;
		System.out.println("year:" + d1.year + " month:" + d1.month + " day:" + d1.day);
	}
} 

这两个类都是public类,所以,这两个类应该写在两个不同的源代码文件中,文件名分别为:Date.java 与TestDate.java中。如果大家想将这两个类写在一个源代码文件中,因为Date类在测试完成以后是会被公开使用的,所以我们应该把Date定义为public,那么源代码文件的名字就是Date.java,而TestDate这个类是用于测试Date类的,所以它前面的public就应该去掉。代码如下:

//这些代码放在Date.java文件中
class TestDate{
	public static void main(String[] args){
		Date d1 = new Date();
		d1.year = 2016;
		d1.month = 9;
		d1.day = 5;
		System.out.println("year:" + d1.year + " month:" + d1.month + " day:" + d1.day);
	}
}

public class Date{
	public int year;
	public int month;
	public int day;
}

这两个类的定义顺序无关紧要。编译后,我们在命令行上执行:java TestDate即可。

思考

封装

在这个示例中,有个问题:我们在创建Date对象d1以后,就直接使用d1.这种形式给year、month、day赋值了,如果我们给它们的值不是一个合法的值怎么办?比如month的值不在1~12之间,等等问题。在如上的Date定义中,我们没有办法控制其他代码对这些public修饰的变量随意设置值。

我们可以把这些成员变量用private修饰词保护起来。由private修饰的成员,只能在类或对象内部自我访问,在外部不能访问,把上面的Date代码改为:

public class Date{
	private int year;
	private int month;
	private int day;
}

这样我们就不可以通过d1.year来访问d1对象中year了。慢着,不能访问year,那这个变量还有什么用?是的,如果没有其它手段,上面的这个类就是无用的一个类,我们根本没有办法在其中存放数据。

怎么办?我们通过为每个private的成员变量增加一对public的方法来对这些变量进行设置值和获取值。这些方法的命名方式为:setXxx和getXxx,setter方法为变量赋值,getter取变量的值,布尔类型的变量的取值用:isXxx命名,Xxx为变量的名字,上例改为:

public class Date{
	private int year;
	private int month;
	private int day;

	public void setYear(int year){
		//理论上year是没有公元0年的,我们对传入的值为0的实参处理为1
		//year的正值表示AD,负值表示BC
		if(year == 0){
			//这里有两个year,一个是成员变量,一个是实参,这是允许的
			//为了区分它们,在成员变量year前面加上this.
			//实参year不做处理
			//如果没有变量和成员变量同名,this是可以不写的
			this.year = 1;
		} else {			
			this.year = year;
		}
	}

	//因为要取的是year的值,所以getter方法的返回值同所取变量的类型一致
	public int getYear(){
		return year;
	}

	public void setMonth(int month){
		if((month > 0) && (month < 13)){
			this.month = month;
		} else{
			this.month = 1;
		}
	}

	public int getMonth(){
		return month;
	}

	public void setDay(int day){
		//这个方法有些复杂,因为我们需要根据year、month的值来判断实参的值是否合规
		switch(month){
			case 1:
			case 3:
			case 5:
			case 7:
			case 8:
			case 10:
			case 12:if (day < 32 && day > 0) {//在1~31范围内
						this.day = day;
					}else{
						this.day = 1;//超出日期正常范围,我们设为1
					}
					break;
			case 4:
			case 6:
			case 9:
			case 11:if (day < 31 && day > 0) {//在1~30范围内
						this.day = day;
					}else{
						this.day = 1;//超出日期正常范围,我们设为1
					}
					break;
			case 2:if (isLeapYear()) {
						if (day < 30 && day > 0) {//在1~29范围内
							this.day = day;
						}else{
							this.day = 1;//超出日期正常范围,我们设为1
						}
					} else {
						if (day < 29 && day > 0) {//在1~28范围内
							this.day = day;
						}else{
							this.day = 1;//超出日期正常范围,我们设为1
						}
					}
					break;
			default:this.day = 1;//如果month的值不在上述情况下,day设置为1		
					break;		
		}
	}

	//这个方法判断年份是否为闰年,是闰年返回true,否则返回false
	//该方法只在本类内部使用,所以定义为private
	private boolean isLeapYear(){
		//可被400整除或者被4整除但不能被100整除的年份为闰年,其它年份为平年
		if((year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0))){
			return true;
		}

		return false;//能执行这里,说明是平年
	}
}

经过上面的改造,虽然代码长了很多,但是安全了很多。我们对year、month、day的值不再是直接存取,而是通过相应变量的getter和setter方法来存取,这些方法在进行存取的时候,会判断设置的值是否合规。

上面的代码其实是可以优化的,比如setDay可以优化如下:

	public void setDay(int day){
		//这个方法有些复杂,因为我们需要根据year、month的值来判断实参的值是否合规
		this.day = 1;//这里先把day设置为1,下面的超范围的情况就不用再写代码了
		switch(month){
			case 1:
			case 3:
			case 5:
			case 7:
			case 8:
			case 10:
			case 12:if (day < 32 && day > 0) {//在1~31范围内
						this.day = day;
					}
					break;
			case 4:
			case 6:
			case 9:
			case 11:if (day < 31 && day > 0) {//在1~30范围内
						this.day = day;
					}
					break;
			case 2:if (isLeapYear()) {
						if (day < 30 && day > 0) {//在1~29范围内
							this.day = day;
						}
					} else {
						if (day < 29 && day > 0) {//在1~28范围内
							this.day = day;
						}
					}
					break;
		}
	}

我们通过上面的示例,看到了面向对象的一个概念:封装。我们将数据用private隐藏起来,通过public存取方法对数据进行了封装,使得数据更加安全与可靠。

成员变量的初始化
非静态成员变量的初始化

在上面的例子中,如果我们新建一个Date对象以后,如果不初始化,我们可以知道,直接取其中的year、month、day的值的时候,它们的值都是0,这显然是不合理的。要解决这个问题,我们需要在创建Date对象的时候,让系统自动初始化一个合适的值,要达到此目的,我们可以采用三种方式:

  • 在定义成员变量的时候初始化值,如上面的代码,我们修改一下如下:

    public class Date{
    	private int year = 1;
    	private int month = 1;
    	private int day = 1;
    
    	...
    
    }
    

    上面的代码,使得新建Date对象的初始值均为1。

  • 第二种方式为使用构造方法

    构造方法是类中一种特别的方法,它的方法名和类名一致,该方法没有返回值,甚至连void都没有,而且构造方法不能被当作普通方法一样被调用,每当生成某个类的对象的时候,构造方法才被调用。构造方法的作用就是在创建对象的时候执行对对象的初始化工作。我们使用构造方法对成员变量来进行初始化,代码如下:

    public class Date{
    	private int year;
    	private int month;
    	private int day;
    
    	public Date(){
    		year = 1;
    		month = 1;
    		day = 1;
    	}
    
    	...
    
    }
    

    上面的代码使得我们在新建Date对象时,可以初始化其内的值。上面的构造方法没有参数,这种构造方法,我们称之为默认构造方法。那是不是用构造方法只能初始化为这种固定的值呢?能不能在创建对象的时候再指定初始化值呢?答案是可以的,就是使用有参数的构造方法。代码如下:

    public class Date{
    	private int year;
    	private int month;
    	private int day;
    
    	public Date(int year, int month, int day){
    		//下面的代码使用setter方法进行初始化是因为,setter方法提供了参数检查,
    		//如果不用setter方法,我们就需要重新写对参数的检查代码
    		setYear(year);
    		setMonth(month);
    		setDay(day);
    	}
    
    	...
    
    }
    

    上面的代码使得我们可以在创建新的Date对象的时候指定初始化值,比如:Date d = new Date(2016,9,5); 。但是上面的代码没有定义无参构造方法,我们再用无参构造方法来创建Date对象就不行了,如:Date d = new Date();,编译时会出现如图的错误:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M22105sq-1652788721442)(https://cdn.jsdelivr.net/gh/yuan-more/cdnDate_nodefaulterror.png)]
    这是为什么呢?这是因为,如果定义类时没有定义构造方法,则编译器会自动创建一个无参的空的public构造方法,作为该类的构造方法。但是,只要你定义了构造方法,不管是有参还是无参,编译器就不再自动生成了,就会出现上面的错误提示。

    另外,在构造方法中产生的异常会被jvm忽略,即使是在构造方法中使用try也无济于事。

    public class Test {
    
    	public Test() {
        	try {
            	System.out.println("trying to throw an exception");
            	double x = 1.0/0.0;//此句会产生除0异常
        	} catch(Exception e) {
            	System.out.println("Exception captured");
       		} finally {
            	System.out.println("inside finally");
        	}
    	}
    
    	public static void main(String args[]) {
        	Test test = new Test();
    	}
    }
    
    

    上述代码在执行以后的结果如图:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JDmqVOjL-1652788721444)(https://cdn.jsdelivr.net/gh/yuan-more/cdnexception_in_constructor.png)] 从图大家可以看到发生的异常并未被catch。

  • 第三种方式是使用实例语句块。那么什么是实例语句块呢?实例语句块是由一对大括号括起来的可以被执行的语句序列,这个语句块在类的内部,但不在任何方法的内部,如下代码:

    public class Date{
    	private int year;
    	private int month;
    	private int day;
    	
    	//下面的大括号为实例语句块
    	{
    		year = 1;
    		month = 1;
    		day = 1;
    	}
    
    	...
    
    }
    

    上面的实例语句块会在构造方法执行前被执行。如果出现多个实例语句块,按顺序执行。

  • 如果这三种方式同时采用呢?代码如下:

    public class Date{
    	private int year = 1;
    	private int month = 1;
    	private int day = 1;
    
    	{
    		year = 2;
    		month = 2;
    		day = 2;
    	}
    	public Date(){
    		year = 3;
    		month = 3;
    		day = 3;
    	}
    
    	...
    
    }
    

    上面的Date类,如果要新建对象,其初始值是1、2,还是3呢?在创建对象的时候,会在堆中为对象分配存储空间再将所分配空间的所有内容都设为默认初始值0,接着将成员变量定义时的值对成员变量进行初始化,再执行实例语句块,最后执行构造方法。因此,上例的初始最终值为3 。

静态成员变量的初始化
  • 我们前面所涉及到的是对非静态成员变量的初始化,我们知道有一类成员变量是用static修饰的,这类成员变量是不依赖对象的,那么这类变量如何初始化呢?
    首先我们要明确,静态成员变量的存储空间不同任何该类的对象相关联,它们的存储空间是独立的。由此,我们可以得出两个结论,首先静态成员变量的值只能被初始化一次,其次,静态成员变量的值不能在构造方法中初始化(因为构造方法是在创建对象的时候调用的)。
    那么怎么对静态成员变量进行初始化呢?有两种方式:

    • 象初始化非静态成员变量一样,直接给静态成员变量赋初始值,如:
      public class Test{
      	public static int first = 1;
      	public static int second = 2; 
      }
      
    • 第二种,使用静态语句块,如下:
      public class Test{
      	public static int first;
      	public static int second;
      	//下面的语句就是静态语句块,这种语句块不能放在方法体中
      	static{
      		first = 1;
      		second = 2;
      	} 
      }
      

    在类中,可以出现多个静态语句块,多个静态语句块顺序执行。

    • 静态成员变量的初始化发生在该成员变量第一次被使用的时候,之后该成员变量不会再重复初始化。而且类中的静态成员变量的初始化发生在非静态成员变量的初始化之前,这样,下面的代码就不合适了:
      public class Test{
      	public int first = 1;
      	public static int second = first;
      }
      
类定义中的成员

Java的类中可以包含两种成员:实例成员和类成员。

实例成员
  • 实例成员(包括实例成员变量及实例方法)属于对象,通过引用访问:
    • 引用变量.实例成员名;
    • 定义类时,如果成员未被static修饰,则所定义的成员为实例成员,如:
    int i=10;
    void f(){…}
    
  • 实例成员的存储分配
    • 通常,类只是描述,通过使用new,对对象进行存储空间分配。未被static所修饰的成员是对象的一部分,因此,这种实例成员的存储分配伴随对象的分配而分配。
    • 例如:
    class T{
    	int i;
    	void f(){}
    }
    。。。
    T t1,t2;
    t1=new T();
    t2=new T();
    
    则此时,i有两个副本,一个在t1中,一个t2中,通过t1.i及t2.i使用
类成员
  • 类成员(包括类成员变量及类方法)属于类,通过类名访问,也可通过引用访问:
    • 类名.类成员名;
    • 定义类时,如果成员被static修饰,则所定义的成员为类成员,如:
    static int count=0;
    public static void main(String args[]){…}
    
  • 类成员的存储分配
    • static用于成员变量前,则不管有多少对象,该成员变量只保留一份公共存储,称为类变量(静态变量);
    • 如果在定义方法时,使用static进行修饰,称为类方法(静态方法),则在调用该static方法,则该方法不依赖具体对象,既是你可以调用某个方法,而不用创建对象。
    • 对于类成员的使用,即可以使用类名使用,也可以通过引用使用,如:
    class T{
    	static int i=47;
    	static void f(){i++;}
    }
    。。。
    T t1,t2;
    t1=new T();
    t2=new T();
    
    则此时,i只有一份,既通过t1.i及t2.i使用,也可通过T.i引用,其值均为47。在执行T.i++;后t1.i及t2.i的值均为48;对f的调用既可以以如t1.f();也可以T.f();方式使用。根据java编程规范,我们建议对于static成员,只采用类名引用的方式。
类成员、实例成员总结
  • 当你使用static就意味着,这个成员变量或方法不依赖于任何该类的对象,所以无需创建对象,就可使用该static数据或方法。
  • 对于non-static 数据和方法则必须创建对象,然后使用该对象操作 non-static 数据和方法。
  • 由此,因为 static 方法不需要创建对象,所以static 方法不能直接存取非static成员。
  • 而non-static 方法则可以直接调用static成员
public class Test{
	static int i=0;
	int j=10;

	static void f(){i++;}
	void s(){f(); j++;}

	public static void main(String[] args){
		Test t=new Test();
		t.s();
		System.out.println(i);
	}
}
  • static的一个重要应用就是无需创建对象而调用方法。比如main( )
  • 在定义一个类时,个性的定义为non-static,共性的定义为static
this

在Java中我们经常看到对this这个关键字地使用。它的使用有两种场合:

  • this作为一个引用用来引用自身,每个对象都有一个this。在类的成员方法中,this用于表示对本对象内的方法或者变量的使用。如果在不会引起歧义的情况下,this是可以省略的。比如上面的一系列setter方法中,因为参数同成员变量同名,为了以示区别,成员变量前的this就不能省略了。

    this不能用在静态方法中。因为静态方法的执行根本不需要java对象的存在,而是直接使用 类名.方法 的方式访问,而this代表的是当前对象,所以在静态方法中根本无法使用this。

  • this可以用在构造方法中,对本类中其它构造方法进行调用

    • 语法:this([实参]);
    • 作用:在一个构造方法中去调用另一个构造方法。
    • 目的:代码重用。
    • this(实参):必须是构造方法中第一个被执行的语句,且只被调用一次。

    我们读读下面的代码

    public class Flower {
    	int petalCount = 0;
    	String s = new String("null");
    
    	Flower(int petals) {
    		petalCount = petals;
    		System.out.println("Constructor with int arg only, petalCount= "+ petalCount);
    	}
    
    	Flower(String ss) {
    		System.out.println("Constructor with String arg only, s=" + ss);
    		s = ss;
    	}
    
    	Flower(String s, int petals) {
    		this(petals); //调用Flower(petals),但不能写作Flower(petals)
    		//! this(s); // Can't call two!
    		this.s = s; // 这是this的另一种使用方式
    		System.out.println("String & int args");
    	}
    
    	Flower() {
    		this("hi", 47);
    		System.out.println("default constructor (no args)");
    	}
    
    	void print() {
    		//! this(11); // Not inside non-constructor!
    		System.out.println("petalCount = " + petalCount + " s = "+ s);
    	}
    
    	public static void main(String[] args) {
    		Flower x = new Flower();
    		x.print();
    	}
    } ///:~
    
    
private构造方法

在构造方法前也可以有public等修饰词用于限定构造方法的存取权限。一般情况下,如果类是public,构造方法也是public,这样通过new才能调用。所以,如果构造方法前面被private 修饰,那会发生什么事情呢?我们在类外就不能生成该类的对象了。大家可以自己测试一下。

那是不是private就不能用在构造方法前面了呢?当然可以,而且这是一种很有用的情况。在有些情况下,有些类在系统中只能允许存在一个该类的实例(对象),这时,我们就可以把该类的构造方法定义为private的。示例代码如下:

public class Handler {
    //handler变量用来保存该类对象的引用
    private static Handler handler = null;
    private Handler() { 
       /* set something here */
    }

	//该类的对象只能通过getHandler方法从handler这个私有变量中获取
    public static getHandler(/* arglist */) {
		//如果handler值非空,说明已经在系统中存在该类的对象,直接取出,不再生成,这就保证了单例
        if (!handler)
             handler = new Handler();
       return handler;
    }

    public static void main(String args[]) {
         Handler.getHandler();
    }
}

jdk-8u144-linux-x64.tar.gz. 该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包 立即下载

相关推荐

RV1106 SDK 软件开发环境

5.30.1 如何开启休眠唤醒功能以project/cfg/BoardConfig_IPC/BoardConfig-SPI_NAND-NONE-RV1106_EVB1_V11-IPC.mk为例:5.30.2 休眠唤醒方案简介SDK的休眠唤醒采用的方案为:进入休眠状态描述:用户层收到触发事件后,暂停业务流程并主动调用echo mem > /sys/power/state命令使系统进入休眠状态。

xzjiang_365的博客 4253

Java语言-定义一个日期Date类。

public class Date { //成员变量 private int day; private int month; private int year; //成员方法 public void setDate(int d,int m,int y) { day=d; month=m; year=y; } public void showDate() { Syst...

程序员本员 5342

【LVGL】学习笔记--(3)界面切换以及显示优化

界面切换和帧率优化

sinat_33408502的博客 1万+

java笔记15 访问控制 内部类 包装 Object中常用的方法

1、访问控制 对象中的属性和方法,是可以根据指定的修饰符来进行访问的。 1.1、概述 类中的属性和方法的四种访问控制: public,公共的,在所有地方都可以访问 protected,受保护的,当前类中,子类中,同一个包中其他类可以访问,不同包中子类,并且创建子类类型的对象,通过子类类型对象可以访问。 default,默认的,当前类中,同一包中的子类中可以访问,注意,default默认的,指的是空修饰符,并不是default这个关键字,除了在接口中要写出来,在其他类中默认不用写出来 private,私

weixin_45331493的博客 153

Unity Tilemap瓦片动态缩放:保持网格尺寸不变的三种实现方案

本文详细探讨了在Unity中实现Tilemap瓦片动态缩放同时保持网格尺寸不变的三种核心方案。针对编辑器静态调整、整体风格化处理及运行时动态控制等不同场景,分别解析了直接修改瓦片属性、调整Tilemap Renderer材质参数以及使用SetTransformMatrix与Matrix4x4矩阵变换的实践方法、优缺点及选型指南,为2D游戏开发提供灵活高效的视觉与交互解决方案。

grass的博客 628

GPU架构(1.1)--介绍 GPU的 VPU(Vision Processing Unit)架构

基于自研的 VPU(Vision Processing Unit)架构,专为高性能图形处理和深度学习设计。VPU 架构通过优化计算单元、内存层次结构、同步机制和指令流水线,提供了卓越的性能和能效。VPU 架构通过优化计算单元、内存层次结构、同步机制和指令流水线,提供了卓越的性能和能效。这种架构不仅适用于高性能图形处理,还广泛应用于深度学习、科学计算和边缘计算等领域。通过了解 VPU 架构的详细设计和工作原理,读者可以更好地利用这些先进的 GPU 技术,开发出高效、可靠的计算系统。

MHD0815的博客 1301

java中有些特殊的类不需要或不能创建实例对象!

一, 不能创建对象的类抽象类(abstract)不能创建对象。这个大家应该都知道,所以在这里就不班门弄斧了。 简单回顾需要注意的几点: 包含抽象方法的类,必须声明为抽象类。 声明为抽象类的类,不一定非要包含抽象方法。 抽象类包含具体数据和具体方法。 抽象类不能创建对象,但可以定义对象变量,来引用非抽象子类的对象 Persion p=new Student();//其中Persion是抽象类,p是对

gao_zhennan的博客 7475

控制科学与工程(自动化)保研经验【2】——南开、同济篇

禁止转载 1、南开人工智能学院夏令营   保研之旅第一个夏令营就是南开,南开夏令营非常早(6月份),当时我们专业仅有两人入营。夏令营前一天我们两个坐高铁来到了天津,几经辗转来到了南开的津南校区,非常偏僻。在自己找的酒店住了一晚,第二天一早去学院报到,资格审查、报销路费等等,然后开营仪式,吃饭,入住酒店,实验室参观。   开营仪式和实验室参观了解到,南开人工智能学院是国内第一批人工智能学院,和很多高...

Control Everything 6535

Java面向对象【上】超详细保姆级讲解 零基础也能学懂

成员变量作用域: 在类的任何地方都有效 非静态变量,只有在创建对象时,才会分配空间并赋值 对象调用并执行某方法之后,成员变量的值发生变化 面向过程和面向对象的区别: 面向过程: 分析出解决问题的步骤,用函数把这些步骤一步一步实现,使用时依次调用。 面向对象: 把问题分解成对象,建立对象的目的是为了描述某个事物在解决问题的步骤中的行为。 this()不能使用在普通方法中,只能在构造,必须是构造的第一条语句 this.方法名称 用来访问本类的成员方法 this(); 访问本类的构造

weixin_62077861的博客 679

手把手入门YOLO到改进优化教程专栏介绍与说明——列表目录查阅(持续更新)

手把手入门YOLO到改进优化教程专栏介绍与说明——列表目录查阅(持续更新)

嵌入式阿齐Archie 2万+

1.DJI-payload SDK负载开发准备和硬件连接及运行示例代码

大疆psdk开发环境

哒宰的博客 1443

零基础入门学java第五节:Java中的运算符

零基础入门学java第五节:Java中的运算符 运算符,顾名思义就是用于运算的符号,比如最简单的+-*/,这些运算符可以用来进行数学运算,举个最简单的栗子: 已知长方形的长为3cm,高为4cm,求长方形的面积。 好,我们先新建一个项目,命名为Rectangle。 然后右键src文件夹,新建一个package,命名为pers.frank.rectangle。 ...

tzllxya的博客 399

8.26华为OD机试真题 新系统 - 仓库查询 (Java/Py/C/C++/Js/Go)

8.26华为OD机试真题 新系统 - 仓库查询 (Java/Py/C/C++/Js/Go)

算法大师! 1745

java学多长时间能独立开发项目_Java从零基础到独立编写游戏项目

讲解方式:全程ppt动画趣味授课教学,注重学员体验课程亮点:1、知识体系化,结构化,并讲解详细,各阶段学习者都能有所收获2、课程中期开始,每一个学习的技术点都能应用到游戏的制作中,保证学以致用无知识盲点课程内容:1. 计算机基础知识2. Java背景与环境搭建3. Java基础语法4. 面向对象编程5. 界面编程6. 2048数字游戏7. 石头迷阵游戏适用人群:1、对 IT 行业感兴趣的零基础人群...

weixin_34164146的博客 823

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

第五节 面向对象 类 方法

一、快捷创建方法 方法名();按ctrl+1;有时候快捷键不能用是冲突导致 可以右键选择 创建参数时加一个 static 所有方法都能用 while跳出循环可以加别名在另一个循环中直接跳出 二、面向对象思想 面向对象是相对于面向过程来讲的,指的是把相关的数据和方法组织为一个整体来看待 面向对象到面向过程,是程序员思想上,从执行者到指挥者的转变 缺点 小的操作有点浪费 三、面向对象三大思想 1.OOA:面向对象分析(Object Oriented Analysis) 2.OOD: 面向对象设计 (Objec

Thinking_Key的博客 647

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Java编程冒险 - 第五节课(面向对象编程(OOP))

欢迎回来,冒险者们!在我们的Java编程之旅中,我们已经一起探索了变量的魔法、控制结构的力量、数组的秩序和字符串的故事。今天,我们即将进入一个充满创造力的新领域——面向对象编程(OOP)。在这里,我们将学习如何塑造我们的代码世界,让它们更加模块化和易于管理。让我们开始吧!面向对象编程(OOP)是一种编程范式,它使用“对象”来表示现实世界中的事物和情景,将数据和操作数据的方法组合在一起。Java 是一种面向对象的编程语言,非常适合学习 OOP。

qq_42892726的博客 881

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

JAVA面向对象编程

JAVA的背景和历史JAVA的特点和应用领域如何安装和配置JAVA开发环境面向对象编程是一种非常流行的编程范式,Java作为一种面向对象编程语言,也广泛使用这种编程范式。本文详细介绍了Java中的面向对象编程基本概念,包括类和对象、封装、继承和多态等。并举例说明了电子商务系统和游戏开发两个实例。希望本文能够帮助初学者更好地理解和掌握Java中的面向对象编程。类和对象的定义和使用Java是一门面向对象编程语言,类和对象是Java中最基本的概念之一。

Kali与编程 1207

【java】兴唐课程第五节到第九节知识点总结

第九节 1、 代码:void readBook(String… bookNames) 表示不确定参数的个数,此时变量为一个数组。 2、当方法中的参数名称(如stuname)和属性名称相同时。 this.stuname表示属性 stuname表示参数。 3、主方法与所在的累无关,是一个程序的入口。 4、如果方法里有return语句则跳出方法。 5、如果方法的返回值非void 则必须有对应类型的返回值...

tyrantForever的博客 215

Java基础第五节

继承、抽象类、接口 5.1 什么是继承?如何完成一个继承关系? 面向对象的特征之一。[封装,继承,多态] 继承是一种通过现有的类,创建出新类的机制。 继承实际上一种类与类之间关系。 代码说明: 首先有一个基类 Thing public class Thing { public Thing() { System.out.println("Everything begins here!"); } } 然后有个子类命名为Shape(形状)继承Thing public cla

weixin_43511745的博客 880

2021Java入门教程,Java从零基础到独立编写游戏项目

随着互联网技术的高速发展,Java作为目前市场应用最广泛的一门编程语言,市场需求大,可选择岗位种类多,使得越来越多的人选择学习Java编程知识,成为Java程序员。 但是,对于零基础的同学来说,由于Java语言自身的抽象程度比较高,在理解很多概念的时候很难建立起画面感,加上缺少编程思维,导致许多初学者,觉得学习Java编程很难。 如果你也想学Java编程开发,还在担心难度大?枯燥?无趣?掉头发?不不不!播妞认为你只是没有遇见,一套足以提起你兴趣的视频教程。 带你快速掌握 Java 2021年黑马程

qq_41293655的博客 359

Java学习第五节

Java学习第五节 一.方法与数组 1.方法与数组 (1)基本数据类型:int,double,float,数组,从本质上来说,它们都是存储数据的容器(container)。与存储单个数据的变量相比较,数组存储的是多个数据,或是多组数据(如map集合等)。 (2)数组引用传递 在Java语言中,b = a(a和b都是引用名)的含义就是将a起个别名"b"。之后,a和b其实就是指向的是同一个对象。在Java中,这种给变量取别名的机制称之为引用(reference)。在现实生活中,“引用”的例子也很多,例如,周树人

weixin_44373385的博客 170

第五节 Java 集合

第五节 Java 集合1. 集合概述1.1 数组与集合之间的区别1.2 集合的分类2. Collection接口3. List接口3.1 ArrayList 集合3.2 LinkedList 集合3.3 Vector集合4. Collection 集合遍历4.1 通过Iterator进遍历4.2 通过增强for来进行遍历4.3 通过集合的forEach(Consumer action)方法来遍历4.4 通过迭代器的forEachRemaining(Consumer action)方法来进行遍历4.5 通过f

fancy_hacker的博客 872

从零基础接触java第五周第五节

上一节跟大家分享了内部内,这一届我要跟大家的分享的是继承以及抽象类。   首先跟大家说说继承吧,所谓的继承,便是一个子类继承父类,关键词:extends,继承有什么好处呢?通过继承,我们能调用父类的方法,减轻我们代码的冗余。那么现在先说一个案列: class Father{ public void pln(){ System.out.println("We are father!");

M_F_X_B_K的博客 439

Java——第五节函数

2501_90980145的博客 148

JAVA WEB 第五节 JDBC

JDBC黑马程序员笔记

qq_52322244的博客 207

Java—零基础学员学习任务总结

本文是帮助初学者从开始学习到入门的一种方法

zf888999666的博客 185
上一篇: 零基础学Java第一节(语法格式、数据类型)
下一篇: 零基础学Java第六节(面向对象二)
Code_ForYou
博客等级 码龄5年 0粉丝 9原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值