形式参数-返回值-内部类-匿名内部类

一.形式参数和返回值

1.基本数据类型:

  你要什么数据类型,实际传参的时候就传什么数据类型,形式参数的改变对实际参数没有影响(String是引用类型,但和基本类型的效果一样String s = "luo")。
关于String:String a = "abc"和String s = new String("abc")的区别
在Java虚拟机(JVM)中存在着一个字符串池,其中保存着很多String对象,并且可以被共享使用,因此它提高了效率。String a = "abc";在执行这个代码的时候,Java虚拟机首先在字符串池pool中查找是否已经存在了“abc”的这么一个对象,判断依据是String类equals(Object obj)方法的返回值。如果有,则不再创建新的对象,直接返回已存在对象的引用;如果没有,则先创建这个对象,然后把它加入到字符串池中,再将它的引用返回。
对于String s = new String("abc");语句,这里“abc”本身就是Pool中的一个对象,而在运行时执行new String()时,将pool中的对象复制一份放到堆中,并且把堆中的这个对象的引用交给s持有,创建了两个String对象。
第二种方式创建了两个String对象,增加了性能开销,所以建议避免使用这种方式创建String对象。
class Demo{
	//成员方法
	public int sum(int a,int b){
		return (a+b);
		
	} 
}


public class BasicDataTest {

	public static void main(String[] args) {
		Demo d = new Demo();
		int result = d.sum(3, 4);      //3、4是实际的两个参数
		System.out.println("result = "+result);
		System.out.println("-------------");
		
		String str1 = "fly";
		String str2 = "weight";
		String str3 = "flyweight";
		String str4 = null;
		
		str4 = str1 + str2;
		System.out.println(str3 == str4);	//false
		
		/*
		 * str3和str4指向同一个对象,通过intern()方法来实现,会先在字符串常量池中寻找内容为“flyweight”的地址,
		如果找到,就将str4变量指向这个地址,如果找不到,就将创建一个字符串常量并将其加入到常量池中,此处已有这个地址,
		所以str4指向这个地址。即str3和str4变量指向为同一个地址,两个引用指向同一个字符串对象。
		*/
		
		str4 = (str1 + str2).intern();
		System.out.println(str3 == str4);	//true

	}

}

2.引用类型:具体类、抽象类、接口

1)具体类:

形式参数:如果形式参数是一个具体的类,那么需要创建该类对象

class Student{
	public void show(){
		System.out.println("好好学Java!");
	}
}

class StudentDemo{
	public void method(Student s){	//形式参数是一个引用类型,那么需要该类对象Student s = new Student();
		s.show();
	}
}

public class ConcreteDemo {

	public static void main(String[] args) {
		//需求:调用StudentDemo中的method()方法,则需要创建StudentDemo这个类的对象
		
		StudentDemo sd = new StudentDemo();
		//创建Student类的对象
		Student s = new Student();
		sd.method(s);    //s代表Student类的对象,把空间地址值作为参数传递
		

	}

}

返回值:方法的返回值是一个具体的类,那么需要创建该类对象

class Student{
	public void show(){
		System.out.println("好好学Java!");
	}
}

class StudentDemo{					//如果方法的返回值是一个具体的类,那么需要该类的对象
	public Student method(){
		/*
		 Student s = new Student();
		return s;
		*/
		return new Student();      //匿名对象
	}
}

public class ConcreteDemo {

	public static void main(String[] args) {
		
		 //需求:调用StudentDemo中的method()方法,则需要创建StudentDemo这个类的对象

		StudentDemo sd = new StudentDemo();
		Student s = sd.method();     //返回的是一个Student类型的对象
		s.show();                    //再调用Student类中的show()方法
	}

}

2)抽象类:

形式参数:需要再定义一个抽象类的子类,来进行实例化(创建对象!)创建对象的实质:抽象类多态!

//声明一个抽象类
abstract class Person{
	public abstract void study();
}

//定义一个PersonDemo类
class PersonDemo{
	//定义一个带有形参的成员方法
	public void method(Person p){	//Person p = new Person()是错误的,因为抽象类不能实例化,
									//需要再声明一个抽象类的子类,通过抽象类多态实例化
		
		p.study();
	}
}

//声明抽象类的子类
class Person2 extends Person{
	//重写抽象类中的抽象方法
	public void study(){
		System.out.println("好好学Java!");
	}
}

//测试类
public class AbstractDemo {
	public static void main(String[] args) {
		//调用PersonDemo中的method()方法;
		PersonDemo pd = new PersonDemo();
		
		//需要使用抽象类多态实现化
		Person p = new Person2();
		pd.method(p);
		
		/*//链式编程: 
		new PersonDemo().method(new Person2());
		*/

	}

}

返回值:返回值如果是抽象类,需要返回的是该抽象类的子类对象

//声明一个抽象类

abstract class Person3{
	public abstract void show();
}

//定义PersonDemo2类
class PersonDemo2{
	public Person3 method(){	//如果一个方法的返回值是一个抽象类,需要返回的是该抽象类的子类对象
		Person3 p = new Person4();
		return p;
		//return new Person4(); 
	}
}

//抽象类的子类
class Person4 extends Person3{
	public void show(){
		System.out.println("爱学习!爱Java!");
	}
}
//测试类
public class ReturnAbstract {
	public static void main(String[] args) {
		//调用PersonDemo2中的method()方法
		PersonDemo2 pd = new PersonDemo2();
		
		
		Person3 p3 = pd.method();    //返回的是Person3的对象
		p3.show();
		System.out.println("---------");
		
		/*
		 //链式编程
		Person3 p3 = new PersonDemo2().method();	
		p3.show();
		 */
	}

}

3)接口

形式参数:如果形式参数是接口的情况,那么需要自定义一个接口的子实现类,然后通过接口多态的形式给接口实例化!

//接口
interface Inter{
	public abstract void love();
}

class TeacherDemo{
	public void method(Inter i){	//接口不能实例化;如果一个方法的形式参数是一个接口,那么需要创建该接口的子实现类对象
		i.love();
	}
}

//接口不能实例化,需要定义接口的子实现类
class Teacher implements  Inter{
	public void love(){
		System.out.println("teacher love Java!");
	}
}

//测试类
public class InterfaceDemo {
	public static void main(String[] args) {
		//调用TeacherDemo中的method()方法
		
		TeacherDemo td = new TeacherDemo();
		//创建该接口对象:通过接口多态
		//Inter i = new Teacher();
		
		//匿名内部类
		Inter i = new Inter(){
			public void love(){
				System.out.println("teacher love Java!");
			}
		};
		td.method(i);
	}

}

返回值:返回值如果是接口类型,需要返回的是该接口子实现类对象(通过子实现类进行实例化!)

//定义接口
interface Inter2{
	public abstract void love();
}

//定义一个返回值是接口的类
class TeacherDemo2{		//如果一个方法的返回值是接口类型,需要返回该接口对应的子实现类的对象
	public Inter2 method(){
		Inter2 i = new Teacher2();
		return i;
		
		//return new Teacher2();
	}
}
//接口的子实现类
class Teacher2 implements Inter2{
	public void love(){
		System.out.println("teacher love Java!");
	}
}

//测试类
public class ReturnInterface {
	public static void main(String[] args) {
		TeacherDemo2 td = new TeacherDemo2();
		Inter2 inter2 = td.method();
		inter2.love();

	}

}

二.内部类

1.概念在一个类中定义另一个类,称为内部类。

eg:在类A中定义一个类B,那么类B是类A的内部类,同理,类A就是类B的外部类。内部类是直接可以访问外部类的成员,包括私有。外部类要访问内部类的成员,必须通过创建内部类的对象访问该内部类的成员。

class Outer{
	//外部类的成员变量
	public int num = 10;
	private int num1 = 20;
	
	//内部类
	class Inner{
		//内部类的成员方法
		public void show(){
			//内部类可以直接访问外部类的成员,包括私有
			System.out.println("num = "+num);
			System.out.println("num1 = "+num1);
			
		}
	}
	
	//外部类的成员方法
	public void method(){
		//外部类不能直接访问内部类,必须创建内部类的对象
		Inner i = new Inner();
		i.show();
	}
	
}
//测试类
public class InnerDemo {
	public static void main(String[] args) {
		Outer o = new Outer();
		o.method();
	}
}


2.内部类的分类:成员内部类、局部内部类

package day_09_10_24;
//外部类
class Outer{
	
	//外部类的成员变量
	public int num = 12;
	
	//成员内部类
	class Inner{
		
	}
	
	//外部类的成员方法
	public void method(){
		//局部内部类
		class Inner2{
	
		}
	}	
}

//测试类
public class InnerClass {
	public static void main(String[] args) {
		
	}

}


1)成员内部类:在外部类的成员位置,测试类中需要访问成员内部类中的成员方法:外部类名.内部类名 对象名 = 外部类对象.内部类对象;

package day_09_10_24;

//外部类
class Outer3{
	//定义外部类的变量
	public int num = 10;
	
	//成员内部类(非静态成员内部类)
	class Inner3{
		//内部类的成员方法(非静态的成员方法)
		public void show(){
			System.out.println("num = "+num);
		}
	}
	
	//外部类的成员方法
	public void method(){
		
	}
}
//测试类
public class MemberInner {

	public static void main(String[] args) {
		/**
		 * 需求:访问Inner3成员内部类中的show()方法
		 * 外部类名.内部类名 对象名 = 外部类对象.内部类对象;
		 */
		
		Outer3.Inner3 oi = new Outer3().new Inner3();
		oi.show();
	}

}

成员内部类修饰符:

private :为了保证数的安全性,外部类访问成员内部类方法:外部类
package day_09_10_24;

class Body{
	public String heart;
	//成员内部类
	private class Inner{
		public void operator(){
			System.out.println("医生做手术");
		}
	}
	
	//成员方法
	public void behave(){
		boolean flag = true;
		if(flag){
			Inner i = new Inner();
			i.operator();
		}
	}
}


public class MemberInnerPrivate {
	public static void main(String[] args) {
		/**
		 * 成员内部类被private修饰,直接创建外部类对象,通过外部类成员方法间接访问内部类成员方法
		 * */
		Body b = new Body();
		b.behave();
	}

}


static: 为了方遍调用,如果成员内部类被static修饰,那么要访问外部类的成员变量,这个变量必须被static修饰
 静态的成员内部类访问该类中的成员方法:
外部类名.内部类名  对象名 = new 外部类名.内部类名();
package day_09_10_24;

class Outer4{
	//外部类的成员变量
	
	public static int num1 = 10;
	public static int num2 = 20;
	/**
	 *对于静态的成员内部类,无论其中的方法是静态的还是非静态的,要访问外部类的成员变量,该变量必须被static修饰 
	 **/
	public static class Inner4{
		//静态的内部成员方法
		public static void show(){
			System.out.println("num1 = "+num1);
			System.out.println("num2 = "+num2);
		}
		
		//非静态的内部类的成员方法
		
		public  void show2(){
			System.out.println("num1 = "+num1);
			System.out.println("num2 = "+num2);
		}
	}	
}
//测试类
public class MemberInnerStatic {
	public static void main(String[] args) {
		/**
		 * 需求:要访问静态成员内部类Inner4里面的show(),show2()方法
		 * 外部类名.内部类名 对象名 = new 外部类名.内部类名();
		 * */
		Outer4.Inner4 oi = new Outer4.Inner4();
		oi.show2();
		oi.show();  //静态方法
		System.out.println("------------");
		//show的另一种访问方法;
		Outer4.Inner4.show();  //静态方法可以直接通过类名方法
		
		
	}

}

2)局部内部类:定义在外局部类的局部位置

局部内部类访问该类中的成员方法:直接创建外部类的对象,通过外部类对象访问外部类方法
结论:无论是局部内部类还是成员内部类(非静态的)都可以直接访问外部类的成员,包括私有成员
package day_09_10_24;

class Outer5{
	public int num1 = 10;
	private int num2 = 20;
	
	//外部类的成员方法
	public void method(){
		//局部变量
		final int num3 = 20;  //自定义常量
		
		//局部内部类
		class Inner5{
			public void show(){
				System.out.println("num1 = "+num1);
				System.out.println("num2 = "+num2);
				
				//局部内部类中访问局部变量
				System.out.println("num3 = "+num3);//jdk1.7才会有这个错误!	jdk1.8--->封装好了,所以不会出现错误!
			}
		}
		
		Inner5 i = new Inner5();
		i.show();
	}
}
//测试类
public class InnerLocal {
	public static void main(String[] args) {
		//对于局部内部类访问该类中的成员方法:创建外部类对象,使用外部类对象调用外部类的成员方法
		Outer5 o = new Outer5();
		o.method();
	}

}


面试题:局部内部类访问局部变量会出现问题?(比如上例中的局部变量num3)
当前局部变量会报错,必须用final修饰;
为什么用final修饰?
由于局部变量是随着方法调用而生产的,随着方法的调用完毕消失,而现在局部位置有一个局部内部类,它要在自己的成员方法位置访问当前的局部变量,必须把变量变成一个常量(需要用final:自定义常量),这样的一个变量的值是永远固定的。

三.匿名内部类

内部类的简化版格式
前提条件:必须存在一个接口或者一个类(可以是具体类,也可以是一个抽象类)
格式
new 接口或者类名{
方法重写;
}
匿名内部类的实质:继承了该类(抽象类)或者是实现了该接口的子类对象
package day_09_10_24;


//定义一个接口
interface Inter9{
	//抽象功能
	public abstract void show();
	public abstract void show2();
}

//外部类
class Outer6{
	//成员方法
	public void method(){
		
		/*//当接口中只有一个方法的情况
		new Inter9(){
			public void show(){
				System.out.println("匿名内部类");
			}
		}.show();
	}*/
	
	
		//匿名内部类.接口中有两个方法的时候
		Inter9 i = new Inter9(){
			//方法重写
			public void show(){
				System.out.println("show匿名内部类");
			}
			
			public void show2(){
				System.out.println("show2匿名内部类");
			}
		};
	
		i.show();
		i.show2();
	}
}
public class InnerDemo2 {

	public static void main(String[] args) {
		Outer6 o = new Outer6();
		o.method();

	}

}
package day_09_10_24;

/**
 * 匿名内部类在开发中的使用
 * */

interface Inter3{
	public abstract void study();
}

class StudentDemo1{
	public void method(Inter3 i){  //形式参数是接口
		i.study();
	}
}

//方式1:
class Adess implements Inter3{
	public void study(){
		System.out.println("好好学习,天天向上。。。");
	}
}

public class OuterTest {

	public static void main(String[] args) {
		//调用StudentDemo1中的method()方法
		StudentDemo1 sd = new StudentDemo1();
		
		Inter3 i = new Adess();
		sd.method(i);
		//i.study();
		System.out.println("---------------");
		
		//方式2:匿名内部类
		StudentDemo1 sd2 = new StudentDemo1();
		sd2.method(new Inter3(){
			//方法重写
			public void study(){
				System.out.println("好好学习,天天向上。。。");
			}
		});
	}

}


package day_09_10_24;
/**
 * 匿名内部类面试题:
		按照要求,补齐代码
			interface Inter { void show(); }
			class Outer { //补齐代码 }
			public class InterTest {
				public static void main(String[] args) {
					  Outer.method().show();
				  }
			}
			要求在控制台输出”HelloWorld”
 
分析:
 * 当前method()能直接被类名调用---->method()方法是一个静态方法static 
 * Outer.method().show()---->Outer.method()返回的是一个对象,拿对象调用show()方法
 * 接口只有一个show()方法,需要重写show()方法
 * */

//接口
interface Inter5{
	public abstract void show(); 
}

//外部类
class Outer8{
	//补齐代码
	public static Inter5 method(){	//返回值是一个接口
		return new Inter5(){
			//重写show方法
			public void show(){
				System.out.println("HelloWorld!");
			}
		};
		
	}
}
//测试类
public class InterTest {
	public static void main(String[] args) {
		Outer8.method().show();

	}

}

package day_09_10_24;
/**
 * 
 * 看程序
 * 面试题:
		要求请填空分别输出30,20,10。
		
		外部类和内部类没有继承关系!
 * */

class Outer7 {
	public int num = 10;
	
	class Inner7 {
		public int num = 20;
		public void show() {
			int num = 30;
			System.out.println(num);  //30
			System.out.println(this.num); //20;this指当前对象
			System.out.println(new Outer7().num);//10;要访问外部类的成员变量:匿名对象 :new 外部类名().成员变量
			//外部类的this限定
			System.out.println(Outer7.this.num);//10
			
		}
	}
}
//测试类
public class InterclassTest {
	public static void main(String[] args) {
		Outer7.Inner7 oi = new Outer7().new Inner7();
		oi.show();
	}
}



你可能感兴趣的:(JavaSE基础)