java知识2-----核心1-面向对象基础-----续1

static 关键字

static关键字的作用

java中可以使用static声明属性和方法,非static声明的属性或者方法,每个对象都占有各自的堆栈空间,如果希望一个属性被所有对象所共同拥有,则可以将其声明为static类型的,声明static类型的属性或方法之后,此属性或方法也称为类方法,可以用类名称直接调用。
static可以声明全局属性

static属性、static方法

static属性存储在全局数据区中,被所有对象所共享。

class Person{	// 定义Person类
	String name ;		// 定义name属性,暂时不封装
	int age ;			// 定义age属性,暂时不封装
	static String country = "A城" ;	// 定义城市属性,有默认值,static
	public Person(String name,int age){
		this.name = name ;
		this.age = age; 
	}
	public void info(){	// 得到信息
		System.out.println("姓名:" + this.name + ",年龄:" + this.age + ",城市:" + country) ;
	}
};
public class StaticDemo03{

	public static void main(String args[]){
		
		Person p1 = new Person("张三",30) ;	 // 实例化对象
		Person p2 = new Person("李四",31) ;	 // 实例化对象
		Person p3 = new Person("王五",32) ;	 // 实例化对象
		System.out.println("--------------- 修改之前 -------------") ;
		p1.info() ;
		p2.info() ;
		p3.info() ;
		Person.country = "B城" ;
		System.out.println("--------------- 修改之后 -------------") ;
		p1.info() ;
		p2.info() ;
		p3.info() ;
	}
};
class Person{	// 定义Person类
	private String name ;		// 定义name属性
	private int age ;			// 定义age属性
	private static String country = "A城" ;	// 定义城市属性,有默认值,static
	public static void setCountry(String c){ // 此方法可以直接由类名称调用
		country = c ;
	}
	public static String getCountry(){
		return country ;
	}
	public Person(String name,int age){
		this.name = name ;
		this.age = age; 
	}
	public void info(){	// 得到信息
		System.out.println("姓名:" + this.name + ",年龄:" + this.age + ",城市:" + country) ;
	}
};
public class StaticDemo04{
	public static void main(String args[]){
		Person p1 = new Person("张三",30) ;	 // 实例化对象
		Person p2 = new Person("李四",31) ;	 // 实例化对象
		Person p3 = new Person("王五",32) ;	 // 实例化对象
		System.out.println("--------------- 修改之前 -------------") ;
		p1.info() ;
		p2.info() ;
		p3.info() ;
		Person.setCountry("B城") ;		// 调用静态方法修改static属性的内容
		System.out.println("--------------- 修改之后 -------------") ;
		p1.info() ;
		p2.info() ;
		p3.info() ;
	}
};

在这里插入图片描述

java中的内存区域划分:
1,栈内存:保存对象名称(保存访问的堆内存的地址)
2,堆内存:保存每个对象的具体属性
3,全局数据区:保存static类型的属性
4,全局代码区:保存所有方法的定义

static的使用限制

使用static方法,不能调用非static的属性或方法。
但是反过来是OK的。
static的属性或者方法,是可以直接调用非static的属性或者方法的。

因为static属性或者方法,可以在对象还没有创建的时候就直接使用类名称进行调用。而非static的属性或方法,则必须在对象实例化之后才可以调用。
也就是说static的属性或者方法,在对象还没有创建的时候就已经开辟好空间了,但是非static的属性或者方法都是在对象创建之后才开盘好空间。

main方法

public static void main(){}

主方法是程序的起点,不需要任何返回值。
static表示此方法可以由类名称直接调用。
【java执行命令其实就是使用类名称直接调用了main方法,只是么有明文之处main,因为系统默认去找的就是main():java 类名称】
系统规定好默认调用的的方法名就是main(),执行的时候,默认找到main()方法,首先调用的也是main()方法。

代码块

java中3种代码块的定义及作用。
所谓的代码块就是指用“{}”括起来的一段代码,根据位置不同,代码块可以分为4种:普通代码块,构造块,静态代码块,同步代码块,其中同步代码块主要出现在多线程中。

普通代码块

直接定义在方法中的代码块称为普通代码块。

public class CodeDemo01{
	public static void main(String args[]){
		{		// 普通代码块
			int x = 30 ;	// 就属于一个局部变量
			System.out.println("普通代码块 --> x = " + x) ;
		}
		int x = 100 ;		// 与局部变量名称相同,两个变量互不影响
		System.out.println("代码块之外 --> x = " + x) ;
	}
};

在这里插入图片描述

构造块

将代码块直接定义在类中,则称为构造块。

class Demo{
	{	// 直接在类中编写代码块,称为构造块
		System.out.println("1、构造块。") ;
	}
	public Demo(){	// 定义构造方法
		System.out.println("2、构造方法。") ;
	}
};
public class CodeDemo02{
	public static void main(String args[]){
		new Demo() ;		// 实例化对象
		new Demo() ;		// 实例化对象
		new Demo() ;		// 实例化对象
	}
};

在这里插入图片描述
构造块优先于构造方法执行,且执行多次,只要一有实例化对象产生,就会执行构造块中的内容。

静态代码块

直接使用static关键字声明的代码块称为静态代码块。

class Demo{
	{	// 直接在类中编写代码块,称为构造块
		System.out.println("1、构造块。") ;
	}
	static{	// 使用static,称为静态代码块
		System.out.println("0、静态代码块") ;
	}
	public Demo(){	// 定义构造方法
		System.out.println("2、构造方法。") ;
	}
};
public class CodeDemo03{
	static{		// 在主方法所在的类中定义静态块
		System.out.println("在主方法所在类中定义的代码块") ;
	}
	public static void main(String args[]){
		new Demo() ;		// 实例化对象
		new Demo() ;		// 实例化对象
		new Demo() ;		// 实例化对象
	}
};

在这里插入图片描述
主方法中的静态代码块,优先于其他类中的静态代码块执行;
静态代码块,优先于构造快,优先于构造方法执行;
就算有多个对象产生,静态块也只执行一次;
静态代码块的主要作用就是为静态属性初始化。

如此说来,是不是不需要主方法,直接有一个静态代码块,程序也是可以运行的呢?

public class CodeDemo04{
	static{
		System.out.println("Hello World!!!") ;
	}
};

在这里插入图片描述
运行成功了,但是报了一个异常,无法找到主方法。
也就是说,虽然执行的静态代码块,但是代码块执行完毕后依然回去找主方法。

如何回避掉这个exception?实现,执行完静态块以后不打印这个异常:

public class CodeDemo04{
	static{
		System.out.println("Hello World!!!") ;
		System.exit(1) ;	// 程序退出
	}
};

在这里插入图片描述
没有主方法,可以使用静态代码块替代。

构造方法私有化–单例模式

构造方法私有化的目的

类的封装不光体现在对属性的封装上,实际上方法也是可以被封装的,当然,方法的封装也包含了对构造方法的封装。
例如以下代码就是对构造方法的封装:

class Singleton{
	private Singleton(){		// 将构造方法进行了封装,私有化	
	}
	public void print(){
		System.out.println("Hello World!!!") ;
	}
};

构造方法私有化,会造成什么影响?

class Singleton{
	private Singleton(){		// 将构造方法进行了封装,私有化	
	}
	public void print(){
		System.out.println("Hello World!!!") ;
	}
};
public class SingletonDemo02{
	public static void main(String args[]){
		Singleton s1 = null ;	// 声明对象
		s1 = new Singleton() ;	// 错误,无法实例化对象
	}
};

私有化的特点是,私有化之后只能在本类中看到,只能在本类中调用,其他类是根本看不到的。方法私有化,这个方法只在本类中可以调用,可以看到。
构造方法私有化之后,该构造方法根本无法在类外面看到,也就是在类外部无法无法实例化对象了。
那只能在类内部实例化对象了。

class Singleton{
	Singleton instance = new Singleton() ;	// 在内部产生本类的实例化对象
	private Singleton(){		// 将构造方法进行了封装,私有化	
	}
	public void print(){
		System.out.println("Hello World!!!") ;
	}
};
public class SingletonDemo03{
	public static void main(String args[]){
		Singleton s1 = null ;	// 声明对象
	}
};

当一个类的构造方法被私有化之后,只能从类的内部取得这个类的实例化对象,那么此时要考虑的,就是如何把类内部生成的instance对象拿到类的外部,这样的话,外部就可以直接通过此对象进行实例化。

class Singleton{
	static Singleton instance = new Singleton() ;	// 在内部产生本类的实例化对象
	private Singleton(){		// 将构造方法进行了封装,私有化	
	}
	public void print(){
		System.out.println("Hello World!!!") ;
	}
};
public class SingletonDemo04{
	public static void main(String args[]){
		Singleton s1 = null ;	// 声明对象
		s1 = Singleton.instance ;	// 取得实例化对象
		s1.print() ;		// 调用方法
	}
};

优化代码:

class Singleton{
	private static Singleton instance = new Singleton() ;	// 在内部产生本类的实例化对象
	public static Singleton getInstance(){		// 通过静态方法取得instance对象
		return instance ;
	}
	private Singleton(){		// 将构造方法进行了封装,私有化	
	}
	public void print(){
		System.out.println("Hello World!!!") ;
	}
};
public class SingletonDemo05{
	public static void main(String args[]){
		Singleton s1 = null ;	// 声明对象
		s1 = Singleton.getInstance() ;	// 取得实例化对象
		s1.print() ;		// 调用方法
	}
};

单例设计模式

class Singleton{
	private static Singleton instance = new Singleton() ;	// 在内部产生本类的实例化对象
	public static Singleton getInstance(){		// 通过静态方法取得instance对象
		return instance ;
	}
	private Singleton(){		// 将构造方法进行了封装,私有化	
	}
	public void print(){
		System.out.println("Hello World!!!") ;
	}
};
public class SingletonDemo05{
	public static void main(String args[]){
		Singleton s1 = null ;	// 声明对象
		Singleton s2 = null ;	// 声明对象
		Singleton s3 = null ;	// 声明对象
		s1 = Singleton.getInstance() ;	// 取得实例化对象
		s2 = Singleton.getInstance() ;	// 取得实例化对象
		s3 = Singleton.getInstance() ;	// 取得实例化对象
		s1.print() ;		// 调用方法
		s2.print() ;		// 调用方法
		s3.print() ;		// 调用方法
	}
};

不管外部声明了多少个Singleton类的对象,最终结果都是通过getInstance()方法取得的实例化对象,也就是说,此时,s1,s2,s3,实际上都使用了一个对象的引用,不管声明多少个对象,最终都是instance对象的引用。
内存关系图:
在这里插入图片描述
这样的设计,在设计模式上来说就是单例设计模式,
如果不希望一个类产生过多的对象的话,就必须使用单例设计模式。
所谓的单例,就是在入口处(构造方法)限制了对象的实例化操作。
单例设计的应用点:全局只有一个实例化对象。

单例设计的核心点就是:
将构造方法私有化,同时在类的内部产生实例化对象,并通过类的静态方法返回此实例化对象的引用。

内部类

在类的内部可以定义另外一个类。在类Outer内部再定义一个类Inner,此时类Inner就称为内部类,而类Outer称为外部类。
内部类可以声明成public或private的。当内部类声明成public或者private的时,对其访问的限制与成员变量和成员方法完全相同。

内部类的优缺点

缺点:类中一般只定义属性和方法,如果定义一个内部类的话,破坏了程序的结构。
优点:使用内部类的最大优点就是可以方便的访问它的外部类的私有属性。

内部类的使用格式

标识符 class 外部类名称{
	//外部类的成员
	标识符  class 内部类名称{
	   //内部类的成员			
	}
}

static声明内部类的作用

class Outer{		// 定义外部类
	private static String info = "hello world" ;	// 定义外部类的私有属性
	class Inner{	// 定义内部类为外部类
		public void print(){				// 定义内部类的方法
			System.out.println(info) ;		// 直接访问外部类的私有属性
		}
	};
	public void fun(){						// 定义外部类的方法
		new Inner().print() ;				// 通过内部类的实例化对象调用方法
	}
};
public class InnerClassDemo03{
	public static void main(String args[]){
		new Outer.Inner().print() ;					// 调用外部类的fun()方法,无法调用会出错
	}
};

以上的内部类Inner是无法在外部直接调用的,是无法按照外部类的形式使用的。

如果一个内部类使用static关键字声明,则此内部类就称为外部类,可以直接通过外部类.内部类的形式进行访问。

class Outer{		// 定义外部类
	private static String info = "hello world" ;	// 定义外部类的私有属性
	static class Inner{	// 使用static定义内部类为外部类
		public void print(){				// 定义内部类的方法
			System.out.println(info) ;		// 直接访问外部类的私有属性
		}
	};
	public void fun(){						// 定义外部类的方法
		new Inner().print() ;				// 通过内部类的实例化对象调用方法
	}
};
public class InnerClassDemo03{
	public static void main(String args[]){
		new Outer.Inner().print() ;					// 调用外部类的fun()方法,可以正确调用
	}
};

使用static可以声明一个内部类,声明的内部类也称为外部类,可以直接在类的外部调用,但是要想在此static内部类中访问其外部类中的属性,则那些属性必须是static的,否则会报错:static方法不能调用非static的属性火法。

一个内部类除了可以通过外部类访问,也可以直接在其他类中调用,但是调用的格式:外部类.内部类 内部类对象 = 外部类实例.new 内部类();
如果一个内部类在外部要被直接访问,而且不想加static的话,就可以通过如下形式,在外部访问内部类。

class Outer{		// 定义外部类
	private String info = "hello world" ;	// 定义外部类的私有属性
	class Inner{	// 定义内部类
		public void print(){				// 定义内部类的方法
			System.out.println(info) ;		// 直接访问外部类的私有属性
		}
	};
	public void fun(){						// 定义外部类的方法
		new Inner().print() ;				// 通过内部类的实例化对象调用方法
	}
};
public class InnerClassDemo04{
	public static void main(String args[]){
		Outer out = new Outer()	;			// 外部类实例化对象
		Outer.Inner in = out.new Inner() ;	// 实例化内部类对象
		in.print() ;						// 调用内部类的方法
	}
};
总结:

1,static声明的内部类,称为外部类,操作的时候要使用 new 外部类.内部类().方法() 的形式访问。

new Outer.Inner().print() ;

2,非static的内部类,要想在外部访问,需要通过 外部类实例.new 内部类().方法() 的形式访问

Out out = new Out();
out.new Inner().print() ;

内部类可以定义在任何位置,可以在类中,可以在方法中,可以在任何代码块中。

使用内部类访问方法中的参数

如果一个方法中的参数或者局部变量,需要被内部类访问的话,需要将此参数或者局部变量定义成final类型的。否则编译会报错。

class Outer{		// 定义外部类
	private String info = "hello world" ;	// 定义外部类的私有属性
	public void fun(final int temp){		// 定义外部类的方法
		class Inner{						// 在方法中定义的内部类
			public void print(){				// 定义内部类的方法
				System.out.println("类中的属性:" + info) ;		// 直接访问外部类的私有属性
				System.out.println("方法中的参数:" + temp) ;
			}
		};
		new Inner().print() ;				// 通过内部类的实例化对象调用方法
	}
};
public class InnerClassDemo05{
	public static void main(String args[]){
		new Outer().fun(30) ;	// 调用外部类的方法
	}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值