`
beginner_dai
  • 浏览: 2388 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类
最新评论

java-接口与内部类

阅读更多
6.1接口
1.接口不是类,而是对类的一组需求描述,类要遵从接口描述的统一格式进行定义。
2.在接口中不能包含实例域或静态方法,不能在接口中实现方法,但可以包含常量。
3.不能使用new来实例化一个接口,但是可以生命一个接口的变量,接口变量必须应用实现了该接口的类对象。
4.如同使用instanceof检查一个对象是否属于某个特定的类一样,也可以使用instanceof检查一个对象是否实现了某个特定的的接口。
5.接口中的方法默认被标记为public,域被标记为public static final。
6.每个类只能拥有一个超类,但却可以实现多个接口。在实现多个接口时,使用逗号将接口分开。
7.实现接口使用关键字implements,使用Arrays类的sort方法对对象数组进行排序时,对象数组中的对象必须实现Comparable接口。
class XXX implements Comparable<xxx>{
	public int compareTo(XXX other){
		return Double.compare(x,other.x);   //x<other.x,则返回-1;x=other.x,则返回0;x>other.x,则返回1;
		//return id-other.id;               
        }
}

8.如果某个类实现了Cloneable接口,Object类中的clone方法皆可以创建类对象的一个克隆。
class XXX implements Comparable, Cloneable
9.问题:为什么java要引入接口概念,为什么不直接将Comparable设计成抽象类。
因为每个类只能扩展一个类,假设这个类已经扩展了一个类,就不能扩展第二个类了。Java是单继承的,不允许多继承,为了弥补这一缺陷,所以出现了接口的实现,主要的原因是多继承会使语言本身变得非常复杂。
6.2对象克隆
1.当拷贝一个变量时,如果只是简单地将原始变量赋值给拷贝变量时,原始变量和拷贝变量将应用通一个对象,任意改变这两个变量中的其中一个,将会对另一个产生影响。
Student stu1 = new Student(); 
	        stu1.setNumber(12345); 
	        Student stu2 = stu1; 
	System.out.println("学生1:" + stu1.getNumber()); 
	        System.out.println("学生2:" + stu2.getNumber()); 
	stu2.setNumber(54321); 
	 
	System.out.println("学生1:" + stu1.getNumber()); 
	System.out.println("学生2:" + stu2.getNumber()); 

学生1:12345
学生2:12345
学生1:54321
学生2:54321
2.如果想要两个变量各自改变而互不影响,就必须使用clone方法。Clone方法是Object类的一个protected方法。
protected native Object clone() throws CloneNotSupportedException;

因为每个类直接或间接的父类都是Object,因此它们都含有clone()方法,但是因为该方法是protected,所以都不能在类外进行访问,不能直接调用。
要想对一个对象进行复制,就需要对clone方法覆盖。
3.如果对象中的所有数据域都属于数值或基本类型,浅拷贝没有任何问题。但是,如果在对象中包含子对象的引用,浅拷贝的结果会使得两个域引用同一个子对象,使得原始对象和拷贝对象共享这部分信息。如果原始对象和浅拷贝对象共享的子对象使补课变得或者是不允许改变的类,将不会产生任何问题。
4.浅拷贝
(1) 被复制的类需要实现Clonenable接口(不实现的话在调用clone方法会抛出CloneNotSupportedException异常) 该接口为标记接口(不含任何方法)
(2) 覆盖clone()方法,访问修饰符设为public。方法中调用super.clone()方法得到需要的复制对象,(native为本地方法)
class Student implements Cloneable{ 
	    private int number; 
	    @Override 
	    public Object clone() { 
	        Student stu = null; 
	        try{ 
	            stu = (Student)super.clone(); 
	        }catch(CloneNotSupportedException e) { 
	            e.printStackTrace(); 
	        } 
	        return stu; 
	    } 
	} 

5.当原始对象中存在一对象的引用时,需要进行深拷贝,这样子对象的引用也不会被影响。
class Address implements Cloneable { 
	    private String add; 
	    @Override 
	    public Object clone() { 
	        Address addr = null; 
	        try{ 
	            addr = (Address)super.clone(); 
	        }catch(CloneNotSupportedException e) { 
	            e.printStackTrace(); 
	        } 
	        return addr; 
	    } 
	} 

	class Student implements Cloneable{ 
	    private int number; 
	 
	    private Address addr; 
	
	    @Override 
	    public Object clone() { 
	        Student stu = null; 
	        try{ 
	            stu = (Student)super.clone();   //浅复制  
	        }catch(CloneNotSupportedException e) { 
	            e.printStackTrace(); 
	        } 
	        stu.addr = (Address)addr.clone();   //深度复制  
	        return stu; 
	    } 
	}

6.所有的数组类型均包含一个clone方法,这个方法已经被设为public,而不是protected。
Int[] array = {2, 3, 4, 5, 6};
Int[] cloned = array.clone();

6.3内部类
1.内部类是定义在另一个类中的类。
2.需要使用内部类的原因:
(1)内部类方法可以访问该类定义所在的作用域(外围类对象)中的数据,包括私有的数据。
(2)内部类可以对同一个包中的其他类隐藏起来。
(3)当想要定义一个回调函数且不想编写大量的代码,使用匿名内部类比较便捷。
3.内部类分为四种:常规内部类,局部内部类,匿名内部类,静态内部类
【1】常规内部类
常规内部类不用static修饰且定义在在外部类类体中。
内部类既可以访问自身的数据域,也可以访问创建它的外围类对象的数据域。
内部类的访问类型可以为public,private和默认的包可见性。
只有内部类可以是私有类,如果为私有类只有外围对象的方法可以构造内部类对象。
外围类引用:外围类.this,例如(TalkingClock.this.beep)
内部对象的构造器:外围类对象.new 内部类(),例如(ActionListener listener = this.new TimePrinter())
在外围类的作用域之外还可以这样引用内部类:OuterClass.InnerClass
编译器将会把内部类翻译成用$分隔外部类名与内部类名的常规类文件,虚拟机并不知晓,例如(TalkingClock$TimePrinter.class)。
public class MyOuter {
 private int x = 100;
 // 创建内部类
 class MyInner {
  private String y = "Hello!";
  public void innerMethod() {
   System.out.println("内部类中 String =" + y);
   System.out.println("外部类中的x =" + x);// 直接访问外部类中的实例变量x
   outerMethod();
   System.out.println("x is" + MyOuter.this.x);
  }
 }
 public void outerMethod() {
  x++;
 }
 public void makeInner() {
//在外部类方法中创建内部类实例
  MyInner in = new MyInner();
 }

 public static void main(String[] args) {
  MyOuter mo = new MyOuter();
  // 使用外部类构造方法创建mo对象
  MyOuter.MyInner inner = mo.new MyInner();//常规内部类需要通过外部类的实例才能创建对象,与实例变量需要通过对象来访问相似
  // 创建inner对象
  inner.innerMethod();
  // TODO Auto-generated method stub
 }
}

【2】局部内部类
如果一个内部类在方法中创建这个类型的对象值使用了一次,就使用局部内部类。在方法体或语句块(包括方法、构造方法、局部块或静态初始化块)内部定义的类成为局部内部类。
局部类不能用public或者private访问修饰符修饰。它的作用域被限定在声明这个局部类的块中。局部内部类只在定义的局部中有效,就想定义的局部变量一样,在定义的方法体外不能创建局部内部类的对象。
1.方法定义局部内部类同方法定义局部变量一样,不能使用private、protected、public等访问修饰说明符修饰,也不能使用static修饰,但可以使用final和   abstract修饰
  2.方法中的内部类可以访问外部类成员。对于方法的参数和局部变量,必须有final修饰才可以访问。
3.static方法中定义的内部类可以访问外部类定义的static成员
public class Jubu {
 private int size=5,y=7;
 public Object makeInner(int localVar){
  final int finalLocalVar=localVar;
  //创建内部类,该类只在makeInner()方法有效,就像局部变量一样。在方法体外部不能创建MyInner类的对象
  class MyInner{
   int y=4;
   public String toString(){
    return "OuterSize:"+size+
        "\nfinalLocalVar"+" "+"this.y="+this.y;
   }
  }
  return new MyInner();
 }
}
class Main{ 
 public static void main(String[] args) {
  Object obj=new Jubu().makeInner(47);//创建Jubu对象obj,并调用它的makeInner()方法,该方法返回一个
  //该方法返回一个MyInner类型的的对象obj,然后调用其同toString方法。
  System.out.println(obj.toString());
  // TODO Auto-generated method stub
 }
} 

【3】匿名内部类
定义类的最终目的是创建一个类的实例,但是如果某个类的实例只是用一次,则可以将类的定义与类的创建,放到与一起完成,或者说在定义类的同时就创建一个类
  以这种方法定义的没有名字的类成为匿名内部类。
   声明和构造匿名内部类的一般格式如下:
new SuperType(construction parameters){
	Inner class method and data
}

new InterfaceType(){
	method and data
}

由于构造器的名字必须和类名相同,而匿名类没有类名,所以匿名类不能有构造器。取而代之的是,将构造器参数传递给超类构造器。尤其是在内部类实现接口的时候,不能有任何构造参数。
public class NiMing {
 private int size=5;
 public Object makeInner(int localVar){
  final int finalLocalVar=localVar;
  return new Object(){
   //使用匿名内部类
   public String toString(){
    return "OuterSize="+size+"\nfinalLocalVar="+finalLocalVar;
   }
  };
 }
public static void main(String args[]){
   Object obj=new NiMing().makeInner(47);
   System.out.println(obj.toString());
 }
}

【4】静态内部类
有时候,使用内部类只是为了把一个类隐藏在另外一个类的内部,并不需要内部类引用外围类对象。为此,可以将内部类声明为static,以便取消产生的引用。在内部类不需要访问外围类对象的时候,应该使用静态内部类。只能访问外部类的static成员,不能直接访问外部类的实例变量,与实例方法,只有通过对象引用才能访问。由于static内部类不具有任何对外部类实例的引用,因此static内部类中不能使用this关键字来访问外部类中的实例成员,但是可以访问外部类中的static成员。
public class MyOuter {
 public static int x=100;
 public static class MyInner{
  private String y="Hello!";
  public void innerMethod(){
   System.out.println("x="+x);
   System.out.println("y="+y);
  }
 }
 public static void main(String[] args) {
  MyOuter.MyInner si=new MyOuter.MyInner();//静态内部类不通过外部实例就可以创建对象;与类变量可以通过类名访问相似
  si.innerMethod();
  // TODO Auto-generated method stub
 }
}


6.4代理
代理可以在运行的时候创建一个实现了一组给定接口的新类。这种功能只有在编译时无法确定需要实现哪个接口时才有必要使用。
代理类具有下列方法:
指定接口所需要的全部方法。
Object类中的全部方法,例如:toString,equals等。
调用处理器是实现了InvocationHandler接口的类对象。调用代理对象的方法,调用处理器的invoke方法都会被调用,兵向其传递Method对象和原始的调用参数。要想代理一个代理对象,需要使用Proxy类的newProxyInstance方法。这个方法有三个参数:
(1) 类加载器,可以用null表示使用默认的类加载器
(2) Class对象数组,每个元素都是需要实现的接口。
(3) 调用处理器,实现了InvocationHandler的类对象。
class TraceHandler implements InvocationHandler{
	private Object target;
public TraceHandler(Object t){
		target = t;
}
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable{
	return m.invoke(target, args);
}
} 
Object value=. . . ;
TraceHandler handler=new TraceHandler(value);
Class[] interfaces = new Class[]{Comparable.class}
Object proxy = Proxy.newProxyInstance(null, interfaces, handler);

如果调用了代理对象的方法就会调用invoke方法。(500.compareTo(288))
代理类是在程序运行过程中创建的,一旦被创建,就变成了常规类。所有的代理类都扩展于Proxy类。一个代理类只有一个实例域——调用处理器,它定义在Proxy的超类中。
对于特定的类加载器和预设的一组接口来说,只有一个代理类,如果使用同一个类加载器和接口数组调用两次newProcyInstance方法的话,只能得到通一个类的两个对象,也可以利用getProxyClass方法获得这个类:Class proxyClass = Proxy.getProxyClass(null,interfaces);代理类一定是public和final。
static bollean isProxyClass(Class c)如果c是一个代理类返回true;

分享到:
评论

相关推荐

    java接口与内部类教学PPT

    接口-与抽象类之区别 6.接口-应用示例(设计模式) 7.内部类-简介 8.内部类-作用 9.内部类-特殊语法规则 10.内部类-安全性 11.内部类-局部内部类 12.内部类-匿名内部类 13.内部类-...

    第讲-接口与内部类优秀文档.ppt

    Java中的接口和内部类是两种高级的面向对象编程特性,它们极大地增强了代码的灵活性和可扩展性。在Java中,接口扮演着契约的角色,它定义了一组方法的签名,但不提供具体的实现。这意味着任何实现了接口的类都必须...

    03-java接口与内部类1

    总结来说,接口和内部类在Java中分别扮演着定义行为规范和增强封装性的角色。接口提供了多继承的解决方案,让代码更加模块化和可扩展;内部类则提供了更灵活的类结构,便于处理复杂的设计需求。理解并熟练运用这些...

    java语言--内部类总结

    《Java语言——内部类详解》 内部类是Java语言中一个独特且强大的特性,它允许我们在一个类的内部定义另一个类。内部类可以提供更复杂的封装,使得代码结构更加清晰,同时还能访问外部类的私有成员,提供了更高级别...

    Java接口和内部类教程

    ### Java接口和内部类教程 #### 3.1 接口 ##### 3.1.1 接口概念的引入 在计算机编程中,接口扮演着至关重要的角色,尤其是在Java这样的面向对象编程语言中。接口可以被视为一种规范或合同,规定了类必须遵循的...

    Java 接口 内部类

    Java接口和内部类是Java语言中两种重要的抽象机制,它们在软件设计中起着关键作用。接口主要用于定义对象之间的交互规范,而内部类则提供了一种封装和隐藏类的机制,使得类的设计更加灵活。 首先,接口是一个合约,...

    Java语言程序设计:JAVA_6-接口与多态、内部类.ppt

    Java语言程序设计:JAVA_6-接口与多态、内部类 接口是Java语言程序设计中的一个重要概念,它定义了一组属性和一组方法。接口中的属性都是public static(可省略)类型的常量,接口中的方法都是public abstract(可...

    Java__接口、内部类和Java_API基础

    "Java接口、内部类和Java_API基础" Java接口是Java语言中的一个抽象概念,它定义了一组方法的集合,但不提供实现。Java接口的主要特点是它不能被实例化,必须由其他类来实现。接口的声明格式为: ``` public ...

    java-1.8.0-openjdk.linux.x86_64

    此外,它还提供了Lambda表达式、函数式接口、Stream API、Optional类等Java 8的新特性,这些特性极大地提升了代码的简洁性和可读性,使得编程更加高效。 对于Linux x86_64架构,这个版本的OpenJDK优化了64位系统上...

    taobao-java-sdk-1.0.0_taoбao_ddsdk_钉钉收_dingtalk_

    《钉钉Java SDK详解与应用实践》 在数字化办公领域,钉钉作为一款深受企业喜爱的协同办公平台,提供了丰富的API接口供开发者进行定制化开发。本文将详细讲解"taobao-java-sdk-1.0.0",这是一个专门用于Java环境下的...

    4_3非访问控制-接口-内部类.pptx

    静态成员不依赖于类的实例就能被访问,而是与类本身关联。这意味着所有类的实例都可以共享静态变量的值,而且可以通过类名直接调用静态方法。例如,`Person`类中的`total`变量就是一个类属性,所有`Person`实例共享...

    编程语言-Java语言-关于内部类的分类和认识

    成员内部类是定义在类的内部且与类的实例相关联的类;局部内部类是定义在方法或作用域内的类;匿名内部类是没有命名的内部类,通常用于实现接口或继承父类;静态内部类是定义在类的内部且与类的实例无关的类。以上是...

    JAVA 内部类 PPT

    Java内部类是Java语言的一个独特特性,它允许我们在一个类的内部定义另一个类。这种设计提供了更高级别的封装和组织代码的方式。以下是关于内部类及其相关知识点的详细说明: 1. **内部类基本语法** - **实例内部...

    mybatis框架压缩包及MySQL驱动包mysql-connector-java-5.1.37-bin.jar

    - 映射器接口:每个SQL映射文件对应一个Java接口,该接口定义了数据库操作的方法,MyBatis会自动实现这个接口。 - SqlSessionFactory:这是MyBatis的核心对象,用于创建SqlSession,它是执行SQL的入口点。 - ...

    yop-java-sdk-2.1.4.zip

    - **示例代码**:可能包含一些简单的Java类,演示如何初始化配置、调用接口并处理结果。 在实际开发中,开发者需要按照附件中的说明,完成以下步骤: 1. 配置`appid`和`appkey`:在项目中找到SDK的配置文件,将从...

    Java内部类总结

    Java内部类主要包括以下几种类型:成员内部类(非静态内部类)、静态内部类(也称为静态嵌套类)、局部内部类和匿名内部类。 - **成员内部类**:这种类型的内部类是定义在外部类的一个成员位置上,它可以访问外部类...

    内部类知识总结3--匿名内部类

    3. **匿名内部类与接口** 匿名内部类可以用来快速实现一个接口的所有方法,这对于实现简单的回调逻辑非常方便。例如,处理按钮点击事件: ```java button.setOnClickListener(new View.OnClickListener() { @...

Global site tag (gtag.js) - Google Analytics