澳门威利斯人_威利斯人娱乐「手机版」

来自 澳门威利斯人 2019-10-06 11:16 的文章
当前位置: 澳门威利斯人 > 澳门威利斯人 > 正文

java编程思想读书笔记二,java自定义泛型

java自定义泛型 面试题:接收大肆数组进行反转,java自定义

决不泛型只好操作某类别型进行反转

代码如下:

package com.swift.fanxing;

import org.junit.Test;

public class RenyiReverse {
    @Test
    public void test() {
        int arr[]=new int[] {1,10,6,9,2};
        reverse(arr);
    }

    public void reverse(int[] arr) {

        for(int i=0;i<arr.length/2;i  ) {

            int temp=arr[i];
            arr[i]=arr[arr.length-1-i];
            arr[arr.length-1-i]=temp;
        }

        for(int x:arr) {
            System.out.println(x);
        }
    }
}

泛型的效能除了集结迭代器上利用,还可采用任性类型类的变量或数组

package com.swift.fanxing;

import org.junit.Test;

public class RenyiReverse {
    @Test
    public void test() {
        Integer arr[]=new Integer[] {1,10,6,9,2};//这里注意不能使用int 替代Integer
        String arr2[]=new String[] {"aa","bb","cc","dd","ee"};
        reverse(arr);
        reverse(arr2);
    }

    public <T> void reverse(T[] arr) {

        for(int i=0;i<arr.length/2;i  ) {

            T temp=arr[i];
            arr[i]=arr[arr.length-1-i];
            arr[arr.length-1-i]=temp;
        }

        for(T x:arr) {
            System.out.println(x);
        }
    }
}

非静态证明在前,静态申明在static之后,类上宣称表示全局,多泛型申明用<T,J,K>

面试题:接收猖獗数组实行反转,java自定义 不用泛型只好操作某类别型举办反转 代码如下: package com.swift.fanxing; import or...

泛型

泛型

  • 对象和实例是三个意思,类与对象的涉及仿佛数据类型和变量同样。

  • 泛型的尤为重要目标之一正是用来钦赐类(如:容器)要具有怎么样类型的指标,代码解释如下:

    public class Holder3<T> {
      private T a;//持有了T的对象,此处可以持有任何对象,可以用Object代替但是要向下转型
      public Holder3(T a) { this.a = a; }
      public void set(T a) { this.a = a; }
      public T get() { return a; }
      public static void main(String[] args) {
        Holder3<Automobile> h3 =
          new Holder3<Automobile>(new Automobile());
        Automobile a = h3.get(); // No cast needed
        // h3.set("Not an Automobile"); // Error
        // h3.set(1); // Error
      }
    } ///:~
    
  • 在有一些场景中会有一个方法再次回到七个指标,你能够使用创制类用它来全数再次回到的四个对象,假若再 加上泛型技能就能在编写翻译期确定保障项目安全。代码解释如下:

    //: net/mindview/util/TwoTuple.java
    package net.mindview.util;
    
    public class TwoTuple<A,B> {
      public final A first;
      public final B second;
      public TwoTuple(A a, B b) { first = a; second = b; }
      public String toString() {
        return "("   first   ", "   second   ")";
      }
    } ///:~
    
  • 要是泛型用得好,基本上不用强制性转变

  • 泛型也足以选拔于接口,比如public interface Generator<T>,在写承袭的时候T能够写成自由等级次序,举例构造一个咖啡工厂public class CoffeeGenerator implements Generator<Coffee>,构造二个生成Fibonacci数列的类public class Fibonacci implements Generator<Integer>,咖啡代码如下:

    //... 省略处为一些简单类,如Latte,Mocha,Cappuccino,Americano,Breve这些类都继承于coffee,coffee.java如下
    package com.generics.coffee;
    public class Coffee {
      private static long counter = 0;
      private final long id = counter  ;
      public String toString() {
        return getClass().getSimpleName()   " "   id;
      }
    } ///:~
    
    //: generics/coffee/CoffeeGenerator.java
    // Generate different types of Coffee:
    package com.generics.coffee;
    import java.util.*;
    import net.mindview.util.*;
    
    public class CoffeeGenerator implements Generator<Coffee> ,Iterable<Coffee> {
      @SuppressWarnings("rawtypes")
      private Class[] types = { Latte.class, Mocha.class,
        Cappuccino.class, Americano.class, Breve.class, };
      private static Random rand = new Random(47);
      public CoffeeGenerator() {}
      // For iteration:
      private int size = 0;
      public CoffeeGenerator(int sz) { size = sz; } 
      public Coffee next() {
        try {
          return (Coffee)
            types[rand.nextInt(types.length)].newInstance();
          // Report programmer errors at run time:
        } catch(Exception e) {
          throw new RuntimeException(e);
        }
      }
      //解释:内部类实现迭代器,该实现了Iterator而CoffeeGenerator实现的是Iterable,要实现foreach循环必须实现这两个接口,
    //从代码看起来foreach循环是看出来了,要理解其本质的原理需要看jvm里面的字节码,new CoffeeGenerator(5)调用后,首先产生
    //CoffeeIterator的实例,执行hasNext()->next()
    //此处可以也可以用匿名内部类
      class CoffeeIterator implements Iterator<Coffee> {
        int count = size;
        public boolean hasNext() { return count > 0; }
        public Coffee next() {
          count--;
          return CoffeeGenerator.this.next();
        }
        public void remove() { // Not implemented
          throw new UnsupportedOperationException();
        }
      };    
      public Iterator<Coffee> iterator() {
        return new CoffeeIterator();
      }
      public static void main(String[] args) {
        CoffeeGenerator gen = new CoffeeGenerator();
        for(int i = 0; i < 5; i  )
          System.out.println(gen.next());
        for(Coffee c : new CoffeeGenerator(5))
          System.out.println(c);
      }
    } /* Output:
    Americano 0
    Latte 1
    Americano 2
    Mocha 3
    Mocha 4
    Breve 5
    Americano 6
    Latte 7
    Cappuccino 8
    Cappuccino 9
    *///:~
    
    Fibonacci数列的代码如下:
    
    package com.generics;
      import net.mindview.util.*;
    
      public class Fibonacci implements Generator<Integer> {
        private int count = 0;
        public Integer next() { return fib(count  ); }
        private int fib(int n) {
          if(n < 2) return 1;
          return fib(n-2)   fib(n-1);
        }
        public static void main(String[] args) {
          Fibonacci gen = new Fibonacci();
          for(int i = 0; i < 18; i  )
            System.out.print(gen.next()   " ");
        }
      } /* Output:
      1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584
      *///:~
    

    只要想要完成迭代,况兼要不要内部类的主意(CoffeeGenerator.java动用的是里面类达成的迭代器情势),用适配器情势达成,适配器格局即把四个互不相干的接口或然类相连接,所以能够选取持续或许组合,UML如下:

    ![](https://www.processon.com/chart_image/thumb/58aaf16ee4b071585833fd96.png)
    
    迭代如下:
    
    package com.generics;
      // Adapt the Fibonacci class to make it Iterable.
      import java.util.*;
      //组合来创建适配器
      public class IterableFibonacci implements Iterable<Integer> {
        private Fibonacci fibonacci = new Fibonacci();
        private int n;
        public IterableFibonacci(int count) { n = count; }
        public Iterator<Integer> iterator() {
        //匿名内部类的形式
        return new Iterator<Integer>() {
        @Override
        public Integer next() {
            // TODO Auto-generated method stub
            n--;
    
            return fibonacci.next();//invoke next() in Fibonacci,for this extends Fibonacci
        }
        @Override
        public boolean hasNext() {
            // TODO Auto-generated method stub
            return n > 0; 
        }
        public void remove() { // Not implemented
                throw new UnsupportedOperationException();
              }
        };
        }   
        public static void main(String[] args) {
          for(int i : new IterableFibonacci(18))
            System.out.print(i   " ");
        }
      } /* Output:
      1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584
      *///:~ 
    
  • 泛型应用于方法

    • 采取于艺术public <T> void f(T x){},其中<T>一定要写,不然编写翻译器是无计可施识别出参数的T

    • 当可变参数与措施结合:

      package com.generics;
      
      //: generics/GenericVarargs.java
      import java.util.*;
      
      public class GenericVarargs {
        //此处的makeList就像是java.util.Arrays里面的asList(T... args);
        public static <T> List<T> makeList(T... args) {
          List<T> result = new ArrayList<T>();
          for(T item : args)
            result.add(item);
          return result;
        }
        public static void main(String[] args) {
          List<String> ls = makeList("A");
          System.out.println(ls);
          ls = makeList("A", "B", "C");
          System.out.println(ls);
          ls = makeList("ABCDEFFHIJKLMNOPQRSTUVWXYZ".split(""));
          System.out.println(ls);
        }
      } /* Output:
                                                  [A]
                                                  [A, B, C]
                                                  [, A, B, C, D, E, F, F, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z]
                                                  *///:~
      

      从地点代码注释可以见见makeList和asList方法很像,上面来探视asList的源码深入分析

        public static <T> List<T> asList(T... a) {
            return new ArrayList<>(a);//此处的ArrayList不是你想的java.util.ArrayList,他是Arrays里面的一个静态内部类
          }
          //此处是静态内部类的构造器,返回一个数组,需要说明的是该内部类并没有实现add,remove等方法,因为asList()方法在大多数使用场景中是不用改变的,所以要构造一个可编辑的ArrayList()用类似下面的代码即可List<WaiterLevel> levelList = new ArrayList<WaiterLevel>(Arrays.asList("a", "b", "c"));  
          ArrayList(E[] array) {
            a = Objects.requireNonNull(array);//判断array是否为空
          }
      
  • 采纳泛型方法对前一章的生成器实行更一步的架空,代码如下:

    //: net/mindview/util/BasicGenerator.java
    // Automatically create a Generator, given a class
    // with a default (no-arg) constructor.
    package net.mindview.util;
    //this class can generate any Class which have default constructor by create() function,but there is a limit which is that constructor cannot pass argument(传参) 
    public class BasicGenerator<T> implements Generator<T> {
      private Class<T> type; 
      public BasicGenerator(Class<T> type){ this.type = type; }
      public T next() {
        try {
          // Assumes type is a public class:
          return type.newInstance();
        } catch(Exception e) {
          throw new RuntimeException(e);
        }
      }
      // Produce a Default generator given a type token:
      public static <T> Generator<T> create(Class<T> type) {
        return new BasicGenerator<T>(type);
      }
    } ///:~
    

    越多的,我们得以对前方提到的元组实行进一步的架空

    //: net/mindview/util/Tuple.java
    // Tuple library using type argument inference.
    package net.mindview.util;
    
    public class Tuple {
      public static <A,B> TwoTuple<A,B> tuple(A a, B b) {
        return new TwoTuple<A,B>(a, b);
      }
      public static <A,B,C> ThreeTuple<A,B,C>
      tuple(A a, B b, C c) {
        return new ThreeTuple<A,B,C>(a, b, c);
      }
      public static <A,B,C,D> FourTuple<A,B,C,D>
      tuple(A a, B b, C c, D d) {
        return new FourTuple<A,B,C,D>(a, b, c, d);
      }
      public static <A,B,C,D,E>
      FiveTuple<A,B,C,D,E> tuple(A a, B b, C c, D d, E e) {
        return new FiveTuple<A,B,C,D,E>(a, b, c, d, e);
      }
    } ///:~
    
  • java对泛型的擦除有四句话

    • 泛型类型在运维时都以Object类型
    • 模板只在编写翻译阶段有效是为着提供编写翻译期的等级次序安全,通过反射操作能够绕过编写翻译阶段
    • 在编写翻译期就可以领略的类型音信是足以操作的
    • 不无在运作时技术明了类型消息的操作都将不可能专门的学问
    package com.generics;
    
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.List;
    class Manipulator<T> {
      public T obj;
      public Manipulator(T x) { obj = x; }
      // Error: cannot find symbol: method f():
      public void manipulate() { 
    //    (obj).f();
      }
    
      public void erase2(){
          //T[] t = new T[4]; 
          //a instanceof T;
      }
    }
    
    public class Manipulation {
      public static void main(String[] args) {
        //1.模板只在编译阶段有效是为了提供编译期的类型安全,通过反射操作可以绕过编译阶段
        List<String> list1 = new ArrayList<>();
        List list = new ArrayList<>();
        list1.add("s");
        //list1.add(2);
        try {
            Method m = ArrayList.class.getMethod("add",Object.class);
            m.invoke(list1, 2);
            System.out.println(list1);
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //2.在编译期就可以知道的类型信息是可以操作的
        HasF hf = new HasF();
        Manipulator<HasF> manipulator =
          new Manipulator<HasF>(hf);
        manipulator.obj.f();
       //在这个函数里面调用的obj.f(),是不可能考虑客户端的类型,即是单独去编译的,在客户端没有调用时,他并不知道T是什么类型,所以有错
        manipulator.manipulate();
    
        //3.所有在运行时才能知道类型信息的操作都将无法工作
        manipulator.erase2();
    
      }
    } ///:~
    
  • 不可能创建泛型类型数组的,日常的缓和方案是在另外想要创设泛型数组的地点都以用ArrayList去创造。

  • 泛型的首要性目的之一是将错误检查测量试验移入到编写翻译期

  • 编译器直接拒相对参数列表中涉及到的通配符的不二法门,即add(? extends fruit)假定产生了这么结果如下图

    图片 1

  • 上面代码可以达成只可以存水果的集合,且在编写翻译期内就能够检查类型新闻,个中第三种方式叫做逆变。为啥逆变的点子得以兑现?答:super关键字表示下界,List<? super Apple> fruit = new ArrayList<>();,而?必供给表示贰个适度的品种,正确来说应该是如此声贝拉米(Bellamy)个实例即:List<? super Apple> fruit = new ArrayList<在这个括号内部必须是Apple的父类>();即在诸如List<? super Apple> fruit = new ArrayList<Fruit>(),所以当add()的时候,能够插入Apple的子类,一样的道理分析List<? extends Apple> flist2 = new ArrayList<那中间要插入的是Apple的子类>();所以当add(new Apple())时候,会失败,比如List<? extends Apple> flist2 = new ArrayList<Jonathan>();Jonathan = new Apple()//error;

    //1.想要实现一个集合里面能装所有类型的水果,但是在编译期不允许装除了水果以外的其他对象
    List<Fruit> flist3 = new ArrayList<>();
    flist3.addAll(Arrays.asList(new Apple()));
    flist3.addAll(Arrays.asList(new Orange()));
    System.out.println(flist3.get(1));
    //2.第一种方式太复杂,下面用逆变的方式实现
    List<? super Fruit> fruit = new ArrayList<>();
    fruit.add(new Apple());
    fruit.add(new Orange());
    
  • 混型即Timestamped<Serialnumbered<Basic>> mixin其中mixin可见调用基类的兼具函数,在C 中,那是一览了解的,可是在java中能够如此注明,但不能调用基类的别样函数只可以调用Timestamped类中的函数,所以必需采纳有个别设计格局来顶替,当中涉嫌到装饰器格局,和用动态代理(即大家得以动态注入类格局)来贯彻混合,不过结果都尚未C 中有益直接。

    implementsextends第一字贯彻:

    package com.generics;
    //: generics/Mixins.java
    import java.util.*;
    
    interface TimeStamped { long getStamp(); }
    
    class TimeStampedImp implements TimeStamped {
      private final long timeStamp;
      public TimeStampedImp() {
        timeStamp = new Date().getTime();
      }
      public long getStamp() { return timeStamp; }
    }
    
    interface SerialNumbered { long getSerialNumber(); }
    
    class SerialNumberedImp implements SerialNumbered {
      private static long counter = 1;
      private final long serialNumber = counter  ;
      public long getSerialNumber() { return serialNumber; }
    }
    
    interface Basic {
      public void set(String val);
      public String get();
    }
    
    class BasicImp implements Basic {
      private String value;
      public void set(String val) { value = val; }
      public String get() { return value; }
    }
    // for Mixin2.java,Timestamped<Serialnumbered<Basic>> mixin = new Timestamped();,mixin can not invoke set() function of Basic,but c   is capable to do it.
    //so in java, use implements and extends keywords to realize it.
    class Mixin extends BasicImp
    implements TimeStamped, SerialNumbered {
    
     //if use this,you must have a instance of response to interface
    
      private TimeStamped timeStamp = new TimeStampedImp();
      private SerialNumbered serialNumber =
        new SerialNumberedImp();
      public long getStamp() { return timeStamp.getStamp(); }
      public long getSerialNumber() {
        return serialNumber.getSerialNumber();
      }
    }
    
    public class Mixins {
      public static void main(String[] args) {
        Mixin mixin1 = new Mixin(), mixin2 = new Mixin();
        mixin1.set("test string 1");
        mixin2.set("test string 2");
        System.out.println(mixin1.get()   " "  
          mixin1.getStamp()    " "   mixin1.getSerialNumber());
        System.out.println(mixin2.get()   " "  
          mixin2.getStamp()    " "   mixin2.getSerialNumber());
      }
    } /* Output: (Sample)
    test string 1 1132437151359 1
    test string 2 1132437151359 2
    *///:~
    

    装饰器格局达成(并不曾完全落到实处):

    package com.generics.decorator;
    
    //: generics/decorator/Decoration.java
    
    import java.util.*;
    
    class Basic {
      private String value;
      public void set(String val) { value = val; }
      public String get() { return value; }
    }
    
    class Decorator extends Basic {
      protected Basic basic;
      public Decorator(Basic basic) { this.basic = basic; }
      public void set(String val) { basic.set(val); }
      public String get() { return basic.get(); }
    }   
    
    class TimeStamped extends Decorator {
      private final long timeStamp;
      public TimeStamped(Basic basic) {
        super(basic);
        timeStamp = new Date().getTime();
      }
      public long getStamp() { return timeStamp; }
    }
    
    class SerialNumbered extends Decorator {
      private static long counter = 1;
      private final long serialNumber = counter  ;
      public SerialNumbered(Basic basic) { super(basic); }
      public long getSerialNumber() { return serialNumber; }
    }   
    
    //this is decoration design patterns
    
    public class Decoration {
      public static void main(String[] args) {
        TimeStamped t = new TimeStamped(new Basic());
      // because timestamped extends Basic
     t.set("fasdfa");
      //realize such as TimeStamped<SerialNumbered<Basic>> mixin1, mixin2
        TimeStamped t2 = new TimeStamped(
          new SerialNumbered(new Basic()));
        //! t2.getSerialNumber(); // Not available, obviously
        SerialNumbered s = new SerialNumbered(new Basic());
        SerialNumbered s2 = new SerialNumbered(
          new TimeStamped(new Basic()));
        //! s2.getStamp(); // Not available
      }
    } ///:~
    

    动态代理格局完成:

    package com.generics;
    
    //: generics/DynamicProxyMixin.java
    import java.lang.reflect.*;
    import java.util.*;
    import net.mindview.util.*;
    import static net.mindview.util.Tuple.*;
    
    class MixinProxy implements InvocationHandler {
      Map<String,Object> delegatesByMethod;
      public MixinProxy(TwoTuple<Object,Class<?>>... pairs) {
        delegatesByMethod = new HashMap<String,Object>();
        for(TwoTuple<Object,Class<?>> pair : pairs) {
          for(Method method : pair.second.getMethods()) {
            String methodName = method.getName();
            System.out.println(methodName   "()");
            // The first interface in the map
            // implements the method.
            if (!delegatesByMethod.containsKey(methodName))
              delegatesByMethod.put(methodName, pair.first);// this is the most important, because this inject all functions of pairs
          }
        }
      } 
      public Object invoke(Object proxy, Method method,
        Object[] args) throws Throwable {
        System.out.println("invoke() is invoked"); 
        String methodName = method.getName();
        Object delegate = delegatesByMethod.get(methodName);
        return method.invoke(delegate, args);
      }
      @SuppressWarnings("unchecked")
      public static Object newInstance(TwoTuple... pairs) {
        Class[] interfaces = new Class[pairs.length];
        for(int i = 0; i < pairs.length; i  ) {
          interfaces[i] = (Class)pairs[i].second;//second represent XXX.class
        }
        ClassLoader cl =
          pairs[0].first.getClass().getClassLoader();
        return Proxy.newProxyInstance(
          cl, interfaces, new MixinProxy(pairs));
      }
    }   
    
    public class DynamicProxyMixin {
      public static void main(String[] args) {
        Object mixin = MixinProxy.newInstance(
          tuple(new BasicImp(), Basic.class),
          tuple(new TimeStampedImp(), TimeStamped.class),
          tuple(new SerialNumberedImp(),SerialNumbered.class));
        //
        Basic b = (Basic)mixin;
        TimeStamped t = (TimeStamped)mixin;
        SerialNumbered s = (SerialNumbered)mixin;
        b.set("Hello");
        System.out.println(b.get());
        System.out.println(t.getStamp());
        System.out.println(s.getSerialNumber());
      }
    } /* get()
    set()
    getStamp()
    getSerialNumber()
    invoke() is invoked
    invoke() is invoked
    Hello
    invoke() is invoked
    1489219456567
    invoke() is invoked
    1
    *///:~
    
  • 静态类型检查即在程序尚未运转时就可见透过检查源代码鲜明项目安全,与动态类型相对应

  • 地下类型机制即直接能够用模板T,而不用钦命该模板属于哪个基类,比方在C 里面就足以平素定义

    template<class T> void perform(T anything) {
      anything.speak();
      anything.sit();
    }
    

    而在java中必须要指明边界

    class Communicate {
    //must specify the bounds of generic type,but C   is not necessary
    public static <T extends Performs> void perform(T performer) {
    performer.speak();
    performer.sit();
    }
    }
    
  • java对潜在类型机制的补充的一种方法是反光,如下

    class CommunicateReflectively {
    //接受一个Object,然后看是哪个类
    public static void perform(Object speaker) {
    Class<?> spkr = speaker.getClass();
    try {
    try {
    Method speak = spkr.getMethod("speak");
    speak.invoke(speaker);
    } catch(NoSuchMethodException e) {
    print(speaker   " cannot speak");
    }
    try {
    Method sit = spkr.getMethod("sit");
    sit.invoke(speaker);
    } catch(NoSuchMethodException e) {
    print(speaker   " cannot sit");
    }
    } catch(Exception e) {
    throw new RuntimeException(speaker.toString(), e);
    }
    }
    }
    
  • 15.17中15.17.2与15.17.3,15.17.4没理解

  • 应用于队列的泛型技艺相当多都会提到到Iterable<T>接口

1.引入

情景方式描述,倘诺实现叁个上学的小孩子的大成的图景:

  • 整数: math=80,english=70
  • 小数: math=85.6,englisth=77.8
  • 字符串: math="66分",english="90.5分"

那么大家理应如何管理吧?大家须要统一筹算的积极分子变量能够吸收接纳不一致的数据类型,大家先是想到的是Object类型

定义Student类,使用Object类型

package com.shxt.demo01;

public class Student {

    private Object math;
    private Object english;

    public Student(Object math, Object english) {
        this.math = math;
        this.english = english;
    }

    public Object getMath() {
        return math;
    }

    public void setMath(Object math) {
        this.math = math;
    }

    public Object getEnglish() {
        return english;
    }

    public void setEnglish(Object english) {
        this.english = english;
    }
}

示范1:设置整型, int → 自动装箱(Integer) → 对象上转型Object

package com.shxt.demo01;

public class Demo01 {
    public static void main(String[] args) {
        Student student = new Student(80,70); //实例化对象并且对数据初始化
        //请注意这种强制只有在JDK7以后才能使用
        int math = (int) student.getMath();
        //JDK7以下的标准写法
        int english = (Integer) student.getEnglish();// Object -> Integer->自动拆箱

        System.out.println("数学成绩:" math ",英语成绩:" english);
    }
}

示范2:设置小数, double → 自动装箱(Double) → 对象上转型Object

package com.shxt.demo01;

public class Demo02 {
    public static void main(String[] args) {
        Student student = new Student(80.7,77.8); //实例化对象并且对数据初始化
        //请注意这种强制只有在JDK7以后才能使用
        double math = (double) student.getMath();
        //JDK7以下的标准写法
        double english = (Double) student.getEnglish();// Object -> Double->自动拆箱

        System.out.println("数学成绩:" math ",英语成绩:" english);
    }
}

示范3:设置字符串, 字符串 → 对象上转型Object

package com.shxt.demo01;

public class Demo03 {
    public static void main(String[] args) {
        Student student = new Student("66分","90.5分"); //实例化对象并且对数据初始化
        String math = (String) student.getMath();
        String english = (String) student.getEnglish();// Object -> String

        System.out.println("数学成绩:" math ",英语成绩:" english);
    }
}

代码解析:

上述的多个测量检验,大家觉得程序应该未有怎么大的主题素材了,真的没反常了吧? 请关怀上边包车型大巴测量检验


示例4:设置整数和字符串,何况转变为字符串的操作进程

package com.shxt.demo01;

public class Demo04 {
    public static void main(String[] args) {
        Student student = new Student(80,"66分"); //实例化对象并且对数据初始化

        String math = (String) student.getMath();
        String english = (String) student.getEnglish();

        System.out.println("数学成绩:" math ",英语成绩:" english);
    }
}

代码剖析: 类型转换错误

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

​ at com.shxt.demo01.Demo04.main(Demo04.java:7

注解大家上述的代码是存在安全隐患的,数据未有到达统一,大家得以透过判别创新代码,那么些不相符大家的须求

决断数据的档次instanceof

package com.shxt.demo01;

public class Demo05 {
    public static void main(String[] args) {
        Student student = new Student(80,"66分"); //实例化对象并且对数据初始化

        String math = null;
        if(student.getMath() instanceof Integer){
            math = String.valueOf(student.getMath());
        }

        String english = (String) student.getEnglish();

        System.out.println("数学成绩:" math ",英语成绩:" english);
    }
}

对数据那样麻烦的推断大家是不想见见的,我们能够通过泛型化解难题

数组

  • 在java中数组是一种成效最高的仓库储存和自由拜访对象应用体系的主意

  • Comparable接口和Comaprator接口用于排序,jdk中选择政策设计形式将“保持不改变的东西与会爆发改造的事物相分离”,代码如下:

    //Comparable
    class Student implements Comparable<Student>{
        private String name;
        private int age;
        private float score;
    
        public Student(String name, int age, float score) {
            this.name = name;
            this.age = age;
            this.score = score;
        }
    
        public String toString()
        {
            return name "tt" age "tt" score;
        }
    
        @Override
        public int compareTo(Student o) {
            // TODO Auto-generated method stub
            if(this.score>o.score)//score是private的,为什么能够直接调用,这是因为在Student类内部
                return -1;//由高到底排序
            else if(this.score<o.score)
                return 1;
            else{
                if(this.age>o.age)
                    return 1;//由底到高排序
                else if(this.age<o.age)
                    return -1;
                else
                    return 0;
            }
        }
    }
    
    public class ComparableDemo01 {
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Student stu[]={new Student("zhangsan",20,90.0f),
                    new Student("lisi",22,90.0f),
                    new Student("wangwu",20,99.0f),
                    new Student("sunliu",22,100.0f)};
            java.util.Arrays.sort(stu);
            for(Student s:stu)
            {
                System.out.println(s);
            }
        }
    }
    
    //Comparator
    package edu.sjtu.ist.comutil;
    
    import java.util.Comparator;
    
    class Student {
        private String name;
        private int age;
        private float score;
    
        public Student(String name, int age, float score) {
            this.name = name;
            this.age = age;
            this.score = score;
        }
    
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public float getScore() {
            return score;
        }
        public void setScore(float score) {
            this.score = score;
        }
    
        public String toString()
        {
            return name "tt" age "tt" score;
        }
    
    }
    
    class StudentComparator implements Comparator<Student>{
    
        @Override
        public int compare(Student o1, Student o2) {
            // TODO Auto-generated method stub
            if(o1.getScore()>o2.getScore())
                return -1;
            else if(o1.getScore()<o2.getScore())
                return 1;
            else{
                if(o1.getAge()>o2.getAge())
                    return 1;
                else if(o1.getAge()<o2.getAge())
                    return -1;
                else 
                    return 0;
            }
        }
    
    }
    public class ComparableDemo02 {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
    
            Student stu[]={new Student("zhangsan",20,90.0f),
                    new Student("lisi",22,90.0f),
                    new Student("wangwu",20,99.0f),
                    new Student("sunliu",22,100.0f)};
            java.util.Arrays.sort(stu,new StudentComparator());
            for(Student s:stu)
            {
                System.out.println(s);
            }
        }
    
    }
    
  • 当你接纳以来的java版本编制程序时,应该事先挑选容器并不是数组,唯有在认证品质成为难点时,你才应该讲程序重构为运用数组

2.初识泛型

  • 概念:泛型正是参数化类型,使用大面积的品类
  • 起因:数据类型不明白
    • 装入数据的连串都被充作Object类型,进而"丢失"了上下一心实际的品种
    • 获取数据时频仍须要转型,作用低,轻易生出错误
  • 作用:
    • 安全: 在编译的时等候检查查数据类型的安全
    • 方便: 全体的强制调换都以机动和隐式的,提升代码的重用率

何以定义泛型?在定义类使用泛型

  • 定义格式,使用<>符号

    class 类名<字母列表>{
      修改符 字母 属性 ;
      修饰符 构造函数(字母 参数名){
    
      }
      修饰符 返回类型 方法(字母 参数名){
    
      }
    }
    
  • 修改Student类如下

    package com.shxt.demo02;
    
    public class Student<T> {
        private T math;
        private T english;
    
        public Student(T math, T english) {
            this.math = math;
            this.english = english;
        }
    
        public T getMath() {
            return math;
        }
    
        public void setMath(T math) {
            this.math = math;
        }
    
        public T getEnglish() {
            return english;
        }
    
        public void setEnglish(T english) {
            this.english = english;
        }
    }
    
  • 泛型海南中国广播公司大的假名列表表明

    • T → Type代表项目
    • K,V → 代表键值中的Key和value
    • E → 代表Element
    • N → 代表Number数字
    • ? → 代表不显然
  • 泛型的运用法则

    • 不可能采纳静态属性和静态方法上
    • 运用的时候须要钦定数据类型
      • 编写翻译时会检查数据的品种
      • 获取数据不再必要强制类型调换
    • 泛型使用是不能够钦赐基本数据类型,只好选取起相应的包装类

演示1:设置统一的数目Float类型

package com.shxt.demo02;

public class Demo01 {
    public static void main(String[] args) {
        Student<Float> student = new Student<Float>(80.7F,77.8F);
        //获取数据不再需要强制类型转换,完成了数据的统一
        Float math = student.getMath();
        Float english = student.getEnglish();

        System.out.println("数学成绩:" math ",英语成绩:" english);

    }
}

容器源码解读

  • 持续结构代码如下:

      public interface Iterable<T>{...}
    
    public interface Collection<E> extends Iterable<E>{...}
    public interface Set<E> extends Collection<E>{...}
    public interface SortedSet<E> extends Set<E>{
    Comparator<? super E> comparator();
    
    }
    public interface List<E> extends Collection<E>{...}
    
  • 抽象类完成接口,能够毫不落成其总体的方法即能够筛选一些情势来落到实处,比如:

interface test{
    void m();
    void f();
  }
  abstract class test2 implements test{
    @Override
    public void m() {
        // TODO Auto-generated method stub
    }
  }

本文由澳门威利斯人发布于澳门威利斯人,转载请注明出处:java编程思想读书笔记二,java自定义泛型

关键词: 澳门威利斯人 JavaSE 泛型 读书笔记