• Beginning Scala study note(9) Scala and Java Interoperability


    1. Translating Java Classes to Scala Classes

      Example 1:

    # a class declaration in Java
    public class Book{}
    
    # Scala equivalent of a class declaration
    class Book

       Example 2:

    # a Java class with a Construtor
    public class Book{
        private final int isbn;
        private final String title;
    
        public Book(int isbn, String title){
            this.isbn = isbn;
            this.title = title;
        }   
    
        public int getIsbn(){
            return isbn;
        }
    
        public String getTitle(){
            return title;
        }   
    }
    
    # Scala equivalent 
    class Book(val isbn: Int, val title: String)

       Example 3:

    # constructor calling superclass in Java
    public class NonFiction extends Book{
        public NOnFiction(String title){
            super(title);
        }
    }
    
    # Scala equivalent
    class NonFiction(title: String) extends Book(title)

       Example 4:

    # mutable instance variable in Java
    public class Book{
        private String title = "Beginning Scala";
    
        public String getTitle(){
            return title;
        }
    
        public void setTitle(String t){
            title = t;
        }
    }
    
    # Scala equialent
    class Book{
        var title = "Beginning Scala"
    }

       Example 5:

    # immutable instance variable in Java
    public class Book{
        private final int isbn = 999;
    
        public int getIsbn(){
            return isbn;
        }
    }
    
    # Scala equivalent
    class Book{
        val isbn = 999
    }

       Translating Java imports to Scala imports:

    # import in Java
    import com.modA.ClassA;
    import com.modB.ClassB1;
    import com.modB.ClassB2;
    import com.modC.*;
    
    # import in Scala
    import com.modA.ClassA
    import com.modB.{ClassB1,ClassB2} // you can stack multiple imports from the same package in braces
    import com.modC._ // underscore in Scala imports is equivalent of * in Java imports

       Example 6:

    # Java class with multiple constructors
    public class Book {
    private Integer isbn;
    private String title;
    public Book(Integer isbn) {
    this.isbn = isbn;
    }
    public Book(Integer isbn, String title) {
    this.isbn = isbn;
    this.title = title;
    }
    public Integer getIsbn() {
    return isbn;
    }
    public void setIsbn(Integer isbn) {
    this.isbn = isbn;
    }
    public String getTitle() {
    return title;
    }
    public void setTitle(String title) {
    this.title = title;
    }}
    
    # refactoring
    class Book(var isbn: Int, var title: String)

        If you create the Book instance with a construtor that takes a single "title" parameter, you will get an error.

    scala> val book = new Book("test")
    <console>:12: error: not enough arguments for constructor Book: (isbn: Int, title: String)Book.
    Unspecified value parameter title.
           val book = new Book("test")

       We need an extra constructor for this case.

    scala> class Book(var isbn: Int, var title: String){
         | def this(title: String) = this(0,title)
         | }
    defined class Book
    scala> val book = new Book("test")
    book: Book = Book@1ab0286
    scala> book.isbn
    res2: Int = 0
    scala> book.title
    res3: String = test

       You can get and set "isbn" and "title" because of the generated getters and setters that follow the Scala conversion.

    2. JavaBeans specification compliant Scala classes

      To have Java-style getters and setters is to annotate the field with scala.beans.BeanProperty. In this way, you can interact with a Java calss or library that accepts only classes that conform to the JavaBean specification.

    scala> import scala.beans.BeanProperty
    import scala.beans.BeanProperty
    
    scala> class Book(@BeanProperty var isbn: Int, @BeanProperty var title: String)
    defined class Book

       After compiling Book.scala with scalac command and disassembling it with javap command:

    public class Book {
      public int isbn();
      public void isbn_$eq(int);
      public void setIsbn(int);
      public java.lang.String title();
      public void title_$eq(java.lang.String);
      public void setTitle(java.lang.String);
      public int getIsbn();
      public java.lang.String getTitle();
      public Book(int, java.lang.String);
    }

        The methods getTitle,setTitle,getIsbn,setIsbn have all been generated because of the @BeanProperty annotation. Note that use the @BeanProperty annotation on your fields, also making sure you declare each field as a var. If you declare your fields a type val, the setter methods won't be generated.

      You can use @BeanProperty annotation on class constructor parameters, even on the fields in a Scala class.

    3. Java interfaces and Scala traits

      A java class can't extend a Scala trait that has implemented methods.

    # A regular Java interface declaration
    
    public interface Book{
        public abstract boolean isBestSeller();      
    }

    # Scala equivalent
    trait Book{ def isBestSeller: Boolean}

       Note that in scala, if there is no  = assignment, then the methods denoted with a def keyword or the functions denoted with a val keyword are abstract. That means if there's no definition provided with =, then it's automatically abstract.

    # a concrete Java method
    public String someMethod(int arg1, boolean arg2){return "voila"}
    
    # Scala equivalent
    def someMethod(arg1: Int, arg2: Boolean) :String = "volia"
    
    # an abstract Java method
    abstract int doTheMath(int i)
    
    # Scala equivalent
    def doTheMath(i: Int): Int

       Example: you need to be able to user an add method from a Java application:

    # a Scala trait
    trait Computation{def add(a: Int, b:Int) = a + b}
    
    # a Java application
    public class DoTheMath{
        public static void main(String[] args){
            DoTheMath d = new DoTheMath();   
        }
    }

       Java class DoTheMath cannot implement the trait Computation because Computation is not like a regular Java interface. To be able to use the implemented method add of a Scala trait Computation from Java class DoTheMath, you must wrap the trait Computation in a Scala class.

    # Scala class that wraps the trait Computation
    class JavaInteroperableComputation extends Computation
    
    # accessing the add method of the Scala trait from Java class
    public class DoTheMath extends JavaInteroperableComputation{
        public static void main(String[] args){
            DoTheMath d = new DoTheMath();
           d.add(3,1);
        }
    }

      Note that wrap you scala traits with implemented behavior in the Scala class for its Java callers.

    4. Java static members and Scala objects

    # a singleton in Scala
    public class Book{
        private static Book book;
        private Book(){}
        public static synchronized Book getInstance(){
            if(book == null){
                book = new Book();
            }
            return book;
        }
    }
    
    # Scala equivalent, object can extend interfaces and traits
    object Book{}

      The companion object enables storing of static methods and from this, you have full access to the class's members, including private ones. Scala alows you to declare both an object and a class of the same name, placing the static members in the object and the instance members in the class.

    # Java class with instance and static methods
    public class Book{
        public String getCategory(){
            return "Non-Fiction";
        }
    
       public static Book createBook(){
            return new Book();
       }   
    }
    
    # Scala equivalent
    class Book{
        def getCategory() = "Non-Fiction"
    }
    
    object Book{
        def createBook() = new Book()
    }

    5.  Handling Exceptions

    # a Scala method that throws an Exceotion
    class SomeClass{
        def aScalaMethod{ throw new Exception("Exception")}
    }
    
    # calling a Scala method from a Java class
    publc static void main(String[] args){
        SomeClass s = new SomeClass();
        s.aScalaMethod();
    }
    
    # the uncaught exception causes the Java method to fail
    [error] (run-main) java.lang.Exception: Exception!
    java.lang.Exception: Exception!
    at SomeClass.aScalaMethod

      For the Java callers of you Scala methods, add the @throws annotation to your Scala methods so they will know which methods can throw exception and what exception they throw.

    # annotating Scala method with @throws
    class SomeClass{
        @throws(classOf[Excepion])
        def aScalaMethod{ throw new Exception("Exception")}
    }

      If you attempt to call aScalaMethod from a Java class without wrapping it in a try/catch block, or declaring that your Java method throws an exception, the compiler will throw an eeor.

    #calling annotated aScalaMethod from Java
    SomeClass s = new SomeClass();
    try{
        s.aScalaMethod();
    }catch(Exception e){
        System.err.println("Caught the exception");
        e.printStackTrace();
    }
  • 相关阅读:
    最近,我和隐私计算干上了。
    面试官疯了吗,问我为什么浮点数不精确?
    全网连夜修复的Log4j漏洞,如何做到一行代码都不改?
    Log4j未平,Logback 又起!再爆漏洞?
    聊聊云原生和微服务架构
    手把手一步一步教你使用Java开发一个大型街机动作闯关类游戏01游戏窗口
    手把手一步一步教你使用Java开发一个大型街机动作闯关类游戏03全屏显示游戏窗口
    手把手一步一步教你使用Java开发一个大型街机动作闯关类游戏02支持中文及显示FPS
    手把手一步一步教你使用Java开发一个大型街机动作闯关类游戏04图像资源的透明处理
    python及pygame雷霆战机游戏项目实战01 控制飞机
  • 原文地址:https://www.cnblogs.com/mengrennwpu/p/6254443.html
Copyright © 2020-2023  润新知