Core Java(五)

第五讲:Object类,内部类,包装类,集合框架

知识点1 什么时候用抽象类?什么时候用接口?

当子类需要一个公用的方法的时候,我们要用抽象类,因为抽象类可以有方法的实现,但是接口不可以,除了这种情况,我们都用接口来实现

 

知识点2 Object

1Equals()方法

比较是否相等,object是所有类的父类

那么它和==有什么区别呢?

等号比较的是值,例如:A a=new A();  A a2=newA();  那么aa2相等吗?用等号比的话是不相等,因为地址的值是不一样的,但是,如果我们只想比较aa2中的属性值,那应该怎么做呢?

这个时候,我们可以使用equals()方法来实现我们的需求,但是,有时候我们需要在子类中重写equals()的方法,因为object里面的equals方法还不能满足我们的需求,自定义的类需要重新写此方法,包装类,string类就不用,已经按我们的要求写好了

2ToString

需求:我们想得到一个对象的属性值,可以同过toString方法来实现

A a=new A();

System.out.println(a);  //System会自动调用toString方法

但是,还需要在自定义的类中重新写这个方法,因为父类的方法不能实现我们的需求,只是返回该对象的地址值转换出来的字符串

 

public class Teacher {

       private String name;

       private int age;

       public Teacher(String name, int age) {

              super();

              // TODO Auto-generated constructor stub

              this.name = name;

              this.age = age;

       }

       public boolean equals(Object arg0) {

              // TODO Auto-generated method stub

              if(arg0 instanceof Teacher){

                     Teacher t=(Teacher)arg0;

                     if(name.equals(t.name)&&age==t.age)

                            return true;

              }

              return false;

       }

       public String toString() {

              // TODO Auto-generated method stub

              return name+age;

       }

}

 

 

public class Testt {

       public static void f(){

              Teacher t1=new Teacher("li",20);

              Teacher t2=new Teacher("li",20);

             

              System.out.println(t1.equals(t2));

              System.out.println(t1);

       }

 

       /**

        * @param args

        */

       public static void main(String[] args) {

              // TODO Auto-generated method stub

              f();

       }

}

 

小技巧1 使用软件自动写出构造器:source->Generat Con. Using

 

小技巧2 自动调用objcet方法:source->G IM

 

知识点3 包装类

Boolean Integer

作用:

1Colleution框架中需要需要使用包装类

2.类型转换的时候用

3Hashcode()

4.包装类有一些好用的属性

String s = "123";

              int i = Integer.parseInt(s);

              i++;

              System.out.println(i);

 

int j = 100;

              Integer jj = new Integer(j);

              int j1 = jj.intValue();

             

              Integer k1 = new Integer(10);

              Integer k2 = new Integer(20);

              Integer k3 = new Integer(k1.intValue() + k2.intValue());

 

知识点4 内部类

1.非静态内部类

2.静态内部类

3.方法内部类

4.匿名内部类

作用:可以方便的访问外部类的成员,包括私有的,当多个父类(接口)出现方法命名冲突时,必须用接口+内部类的方式才能完全实现多继承

掌握几个问题:

1.内部类访问外部类

2.内部类访问另一个文件中的类

3.外部类访问内部类

4.另一个类访问内部类

首先,我们要知道什么是直接访问和常规访问

1.静态方法可以直接访问静态的成员,不能直接访问非静态成员,但是可以常规访问,常规访问就是通过实例化对象来调用成员

class A{

private static int i=10;

private int j=0;

public static void f(){

System.out.println(i);

//System.out.println(j); 不能直接访问非静态成员

A a=new A();

System.out.println(a.j); 可以常规访问常规访问就是通过实例化对象来调用成员

}

}

2.非静态的方法可以直接访问所有成员

注意:这两点是说在同一个类可以这么理解

 

非静态内部类:

public class Nostatic {

       private int a=10;

       private static int b=20;

      

       public void N_f1(){

              System.out.println("nostatic's n_f1()");

       }

      

       public static void N_f2(){

              System.out.println("nostatic's n_f2()");

       }

      

       class inner{

              //非静态内部类不能定义静态成员

              //private static int a1=10;

              public int ia=1;

             

              void i_f1(){

                     System.out.println("i's i_f1()");

                     //访问外部类的成员,都可以访问,包括静态的,非静态的,直接访问

                     System.out.println(a);

                     System.out.println(b);

                     N_f1();

                     N_f2();

              }

              //内部类访问另一个文件中的类

              void i_f2(){

                     //直接做个实例访问

                     Test t1=new Test();

                     t1.t_f();

              }

             

       }

      

//   外部类的非静态方法,访问非静态内部类的非静态方法

       public void N_f3(){

              inner in=new inner();

              in.i_f1();

              in.i_f2();

       }

      

//   外部类的静态方法,访问非静态内部类的非静态方法

       public static void N_f4(){

              //第一步,先构造外部类的一个实例

              Nostatic ns=new Nostatic();

              //第二步,构造内部类的实例

              inner in=ns.new inner();

              //第三步,调用内部类的方法

              in.i_f1();

              in.i_f2();     

       }

 

}

 

//另一个文件的类

public class Test {

       public void f1(){

              System.out.println("Test's f1()");

       }

 

 

 

 

       public static void main(String[] args) {

              // TODO Auto-generated method stub

              Outer out = new Outer();

              Outer.Inner inner = out.new Inner();

              inner.inner_f1();

       }

 

}

非静态内部类总结:

1.在非静态内部类中不能定义静态成员

2.访问外部类的成员:直接访问所有外部类的成员

3.访问另一个文件中的类:常规访问(实例对象,对象调用成员)

4.外部类的非静态方法访问非静态内部类:常规访问(构造内部类的对象,对象调用成员)

5.外部类的静态方法访问非静态内部类:因为静态方法不能直接访问非静态成员,所以,这里比较特殊,先构造外部类的对象,再构造内部类的对象,然后通过内部类的对象调用内部类的成员,注意,构造内部类的对象格式不大一样

语法:[内部类] [内部类引用]=[外部类引用].new [内部类]();

6.另一个文件中的类访问非静态内部类:因为你要访问的是内部类,所以,先构造外部类的对象,然后,再构造内部类的对象,对象调用成员,语法比较特殊

语法:[外部类] [外部类引用]=new [外部类]();

[外部类].[内部类] [内部类引用]=[外部类引用].new [内部类]();

这里为什么是[外部类].[内部类]呢,想想如果写成[内部类] [内部类引用]那么如何区别是实例的外部类还是内部类呢,所以这么写可以加以区分,那为什么外部类的静态方法访问非静态内部类的时候,前面不加[外部类]呢,看第五点的语法,那是因为本来就是自己的内部类,就没有必要加上[外部类]区分了

 

静态内部类:

/*

 *1 静态方法只能直接访问静态成员,如果想访问非静态的成员,需要构造一个对方的实例

  2 非静态的方法可以访问静态的和非静态的方法和属性

  但是,内部类的情况有些变化

 */

 

public class statics {

       private int i=10;

       private static int j;

      

       public void s_f1(){

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

       }

      

       public static void s_f2(){

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

       }

      

       static class Inner{

           int ia=5;

              static int ib=10;

             

              public void i_f1(){

                     //静态内部类的方法不能直接访问外部类的非静态成员,只是构造一个外部类的实例访问

                     //可以直接访问外部类的静态成员

                     System.out.println(j);

                     s_f2();

                     statics ss=new statics();

                     System.out.println(ss.i);

                     ss.s_f1();

              }

             

              public static void i_f2(){

                     System.out.println(j);

                     s_f2();

              }

       }

      

//   外部类的非静态方法,访问内部类的方法

       public void s_f3(){

              //第一种方法

              System.out.println(Inner.ib);

              Inner.i_f2();

              //第二种方法

              Inner in=new Inner();

              in.i_f1();

              in.i_f2();

             

       }

//   外部类的静态方法,访问内部类的方法

       public static void s_f4(){

              Inner.i_f2();

              System.out.println(Inner.ib);

             

              Inner in=new Inner();

              in.i_f1();

              in.i_f2();

       }

 

}

 

//另一个文件中的类访问静态内部类

public class Test {

 

 

       public static void main(String[] args) {

              statics.Inner inner=new statics.Inner();

             

       }

 

}

静态内部类总结:

1.静态内部类可以定义所有成员(静态和非静态)

2.静态内部类的所有类型方法(静态和非静态方法)访问外部类的成员:静态内部类的所有类型方法可以直接访问外部类的静态成员,常规访问外部类的非静态成员(也就是通过实例化外部类的一个对象,对象再调用成员)

3.访问另一个文件中的类:常规访问(实例对象,对象调用成员)

4.外部类的所有类型的方法访问内部类的方法:访问静态成员的常规访问(.静态成员或对象访问)

5.另一个文件中的类访问静态内部类:我们应该站在如何访问静态成员的角度来理解语法就可以了

语法:[外部类].[内部类] [内部类引用]=new [外部类].[内部类]();

 

方法内部类:

1.      类前不加publicprivate

2.      可以访问外部类的私有属性

3.      可以访问外部类方法中的的局部变量,但是要求必须是final的,参数也是一样

public class Outer {

       private int i = 10;

      

       public void  outer_f1(final int k){

              final int j = 20;

             

              class Inner{

                     public Inner(){

                            inner_f1();

                     }

                     void inner_f1(){

                            System.out.println(i);

                            System.out.println(j);

                            System.out.println(k);

                     }

              }

             

              new Inner();

       }

 

       /**

        * @param args

        */

       public static void main(String[] args) {

              // TODO Auto-generated method stub

    Outer o=new Outer();

    o.outer_f1(20);

       }

 

}

 

匿名内部类:

缺点:不方便重用

优点:简洁,清楚

1.不能定义构造器,不用写class

2.实现的是一个接口和方法,指向匿名内部类的对象

 

第一种方式://直接在方法中写匿名内部类

public class Outer {

       public static void test1(){

              Greeting greet = new GreetingImpl();

              greet.hello();

             

       }

      

       public static void test2(){

              Greeting greet = new Greeting(){

                     public void hello() {

                            // TODO Auto-generated method stub

                            System.out.println("Hello world");

                     }

              };

              greet.hello();

       }

 

       /**

        * @param args

        */

       public static void main(String[] args) {

              // TODO Auto-generated method stub

              test1();

       }

 

}

 

interface  Greeting{

       void hello();

}

 

class GreetingImpl implements Greeting{

 

       public void hello() {

              // TODO Auto-generated method stub

              System.out.println("Hello World!");

       }

      

}

 

//第二种方式:可以当作参数来调用

 

知识点5 集合框架Collection

1Collection

什么是框架?用来管理对象的一个集合

有什么作用呢?管理对象用的

collection声明了容器类的一些公用的方法,例如:add,get,remove,iterator,这几个方法以后会解释

2Set

什么是set?集合接口,什么是集合接口呢?放在集合里面的对象必须是唯一的,但是顺序是不定的,也就是说,用户按顺序添加一些对象,它不会按你添加的顺序来显示,你多添加几个一样的对象,它只显示一个,相同的不显示

setlist体现了接口隔离原则

set有两个分支:HashSetTreeSet

 

 

 

那么什么是哈希?这里我们要讲到哈希算法

什么是哈希算法呢?指如何给对象分配地址位置

例如:有5个对象  A,B,C,D,E 在实际中,我们无法确定有多少个对象,假如我们的哈希表的长度是4,也就是从0—3,因为哈希表的长度是从0开始的,将这五个对象放到这4个位置中,应该怎么放呢?我们可以给每个对象指定hashcode值,用hashcode%哈希表的长度,得出来的值,就是该对象在哈希表中的位置,那么如果有相同的值,就在位置的后面再指向一个位置,就是拖车,但是这样就降低了程序的效率了,所以我们尽量让hashcode值唯一,尽管现在不能实现这一目标

 

知识点分之1hashSet

什么是hashSet?哈希集合,基于哈希表的,它是一个底层的数组,元素无序,且不可重复,无序指的是数据的添加顺序和后来的显示顺序不同

自定义的类需要重写equals()hashcode()这两个方法,因为父类的这两个方法不能满足我们的要求,一个要求是按两个对象的属性值来比较,另一个是确定hashcode值,尽可能的保证是唯一的

public class A {

   private String name;

   private int age;

public A(String name, int age) {

 

       this.name = name;

       this.age = age;

}

public boolean equals(Object arg0) {

       boolean rst=false;

       if(arg0 instanceof A){

              A aa=(A)arg0;

              if(aa.name.equals(name)&&age==aa.age){

                     rst=true;

              }

       }

       return rst;

}

public String toString() {

       return name+age;

}

 

public int hashCode() {

       int a=new Integer(age).hashCode()^+name.hashCode();

       return a;

}

public int getAge() {

       return age;

}

public void setAge(int age) {

       this.age = age;

}

public String getName() {

       return name;

}

public void setName(String name) {

       this.name = name;

}

 

}

//man函数类

import java.util.*;

public class Test {

      

       public static void test(){

              Set set=new HashSet();

              A a1=new A("li",20);

              A a2=new A("liu",25);

              A a3=new A("zhao",18);

              set.add(a1);

              set.add(a2);

              set.add(a3);

              A a4=new A("zhao",18);

              set.add(a4);

              System.out.println(set);

       }

 

 

       public static void main(String[] args) {

              // TODO Auto-generated method stub

test();

       }

 

}

 

注意:如果对象换成String或者是包装类,核心类的话就不用重写equalshashcode的了

hashset的优点:底层是数组,查询效率高,在增删操作时,由于运用hashcode的比较,确定元素的位置,从而不存在元素的偏移,效率也很高,但是他是以占用大量的空间为代价的

 

知识点分之2TreeSet

什么是TreeSet?有序集合,象二叉排序树,如果我们需要给对象进行排序的话,可以用它

缺点:消耗太多的资源

作用:

1.实现排序

2.实现排序的目的是从集合中以有序的方式抽取对象,添加到TreeSet的对象必须是可以排序的

3.一般我们先将对象添加到hashSet,再把它转换为TreeSet,这样效率更高

实现排序的方法:

1.自定义类通过实现implements Comparable接口中的compareTo方法制定排序的规则,从而实现TreeSet排序的功能,其他的类不用写(包装类,String类等),因为已经写好了

2.给TreeSet提供了实现Comparator接口的比较器

注意:在对象已经实现Comparable接口,并且也传递给TreeSet相应

的比较器的情况下,那么TreeSet会采用比较器

 

sutdent类实现了Comparable接口中的方法,第一种方法排序

import java.util.*;

public class Student implements Comparable{

       private String name;

 

       private int age;

 

       private double fen;

 

       public Student(String name, int age, double fen) {

              this.name = name;

              this.age = age;

              this.fen = fen;

       }

 

       public int getAge() {

              return age;

       }

 

       public void setAge(int age) {

              this.age = age;

       }

 

       public double getFen() {

              return fen;

       }

 

       public void setFen(double fen) {

              this.fen = fen;

       }

 

       public String getName() {

              return name;

       }

 

       public void setName(String name) {

              this.name = name;

       }

 

       public int compareTo(Object arg0) {

              Student s=(Student)arg0;

              //int rst=(int)(s.fen-this.fen);

              int rst=new Double(s.fen).compareTo(new Double(this.fen));

              if(rst==0){

                     rst=s.name.compareTo(this.name);//String类型已经写好了compareTo方法

                     if(rst==0){

                            rst=s.age-this.age;

                     }

              }

              return rst;

       }

 

       public String toString() {

              // TODO Auto-generated method stub

              return name+age+fen;

       }

 

}

StuComparator类:实现了Comparator接口中的compare方法,第二种排序方法

import java.util.*;

public class StuComparator implements Comparator{

 

       public int compare(Object arg0, Object arg1) {

              // TODO Auto-generated method stub

              Student s1=(Student)arg0;

              Student s2=(Student)arg1;

              //两中方法可以进行比较,一,相减 二,使用compareTo方法

       //   int rst=new Double(s1.getFen()).compareTo(new Double(s2.getFen()));

       //   int rst=new Double(s1.getFen()).compare(new Double(s2.getFen()));

              int rst=(int)(s1.getFen()-s2.getFen());

              if(rst==0){

                     rst=s1.getAge()-s2.getAge();

                     if(rst==0){

                            rst=s1.getName().compareTo(s2.getName());

                     }

              }

             

              return -rst;

       }

 

}

 

主函数:测试两种排序方法

package MY.collection.set.TreeSet;

import java.util.*;

public class TestStudent {

       public static void test(){

              TreeSet ts=new TreeSet();

              Student s1=new Student("li",20,80.0);

              Student s2=new Student("zhang",22,90.0);

              Student s3=new Student("sun",25,70.0);

              Student s4=new Student("sun",22,70.0);

              ts.add(s1);

              ts.add(s2);

              ts.add(s3);

              ts.add(s4);

//当输出这些对象的时候,会自动调用tostring方法,并且需要调用排序规则的方法

//有两种方式可以实现排序规则

              System.out.println(ts);

       }

      

       public static void test2(){

              Student s1=new Student("li",20,80.0);

              Student s2=new Student("zhang",22,90.0);

              Student s3=new Student("sun",21,70.0);

              Student s4=new Student("sun",25,70.0);

              StuComparator stu=new StuComparator();

              TreeSet ts=new TreeSet(stu);

              ts.add(s1);

              ts.add(s2);

              ts.add(s3);

              ts.add(s4);

              System.out.println(ts);

       }

 

       public static void main(String[] args) {

              test();

              //test2();

       }

 

} 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值