Мы предлагаем вам столь необходимый Розеттский камень - объяснительный мост между этими двумя технологиями.

Java и C # невероятно похожи. Оба языка в некоторой степени унаследованы от C ++ и основаны на схожих принципах.

Java была разработана в 1995 году для создания языка с более простой моделью программирования, чем C ++, но с сохранением некоторого синтаксиса языка, чтобы облегчить переход разработчиков на него.

C # был разработан Microsoft в 2000 году как часть своего .NET-диска с целью разработки языка и набора технологий, которые могли бы устранить некоторые из предполагаемых недостатков языка C ++. Он также был разработан с довольно сильным «вдохновением» из языка Java.

Несмотря на сходство между языками и общие точки соприкосновения, переход от одной технологии к другой для разработчика, хорошо разбирающегося в одной технологии, может быть довольно сложным.

Инновации лучше всего происходят, когда есть сотрудничество между людьми с разным мировоззрением, но пользователи C # и Java могут быть несколько племенными.

С этой целью я подумал, что было бы полезно составить своего рода руководство, которое поможет людям задуматься об этих двух технологиях или начать переход между ними. Также было бы неплохо в некотором роде облегчить немного большее сотрудничество между этими двумя мирами - надеюсь, чтобы внести свой вклад в сокращение ненужной пропасти, которая существует между ними.

Некоторые сходства сразу же:

Java - это язык, который работает в среде виртуальной машины (JVM) и запускает байт-код, который генерирует компилятор Java.

Для C # ситуация аналогичная. Это язык, работающий на .NET framework и среде выполнения CLR. Он использует аналогичный для байт-кода Java язык-посредник под названием MSIL, который запускается через CLR.

Именование и условные обозначения

Вот некоторые из ключевых и наиболее очевидных различий в номенклатуре, синтаксисе и условных обозначениях:

  • «Проекты» (Java) - «Решения» (C #)
  • В Java методы используют lowerCamelCase (bar.doAThing()), в то время как в общедоступных методах C # используется PascalCase (bar.DoAThing())
  • В C # интерфейсы всегда имеют префикс I, как в IUserService<T>, вместо UserService<T> в Java.
  • В Java строка - это String - в C # строка - это string
  • «POJO» (Java) - «POCO» (C #)
  • Пакеты (Java) - Пространства имен (C #)

Пакет (Java)

package dev.andymacdonald;
// Code goes here

Пространство имен (C #)

namespace Dev.AndyMacdonald 
{
  // Code goes here
}

Синтаксис

В Java есть final переменных - в C # есть readonly

Ключевое отличие здесь состоит в том, что переменные Java final могут быть назначены один раз в любом месте класса, тогда как переменные readonly C # могут быть назначены только в конструкторе.

В C # есть параметры out и ref, позволяющие передавать аргументы по ссылке - в Java нет

Java фактически не передается по ссылке в аргументах метода.

Он может управлять объектами и переменными по ссылке, но в методе эти аргументы передаются в виде значения. В C # мы можем переопределить это поведение с помощью ключевых слов out и ref.

Аннотации (Java) - атрибуты (C #)

Это в основном эквивалентные концепции, которые отличаются только фактическим синтаксисом. К аннотациям и атрибутам можно получить доступ через соответствующую реализацию Reflection API для каждого языка.

Аннотация Java:

@PersonallyIdentifiable
private String fullName;

Атрибут C #:

[PersonallyIdentifiable]
private string fullName;

Геттеры и сеттеры или Project Lombok (Java) - свойства C #

Здесь C # действительно обгоняет Java благодаря встроенной функции свойств . В стандартном JDK нет эквивалента этому, и вместо этого в Java, геттеры и сеттеры должны быть написаны для каждого поля, требующего средства доступа.

Они часто просто генерируются разработчиком с помощью своей IDE в качестве чит-кода… хотя все еще немного утомительны.

Геттеры и сеттеры Java:

public class Element 
{
   
  private String symbol;   
  private String name;   
  private int atomicNumber;
  public int getAtomicNumber() 
  {
    return this.atomicNumber;
  }
  public String getSymbol() 
  {
    return this.symbol;
  }
  public String getName() 
  {
    return this.name; 
  }
  public void setAtomicNumber(int atomicNumber) 
  {
    this.atomicNumber = atomicNumber;
  }
  public void setName(String name) 
  {
    this.name = name;
  }
  public void setSymbol(String symbol) 
  {
    this.symbol = symbol;
  }
}

Многие проекты Java включают Project Lombok, который добавляет методы получения, установки, равенства и хэш-код (плюс другие полезные шаблоны) во время компиляции.

Project Lombok - не входит в стандартную библиотеку:

@Getter @Setter
public class Element 
{
   
  private String symbol;   
  private String name;   
  private int atomicNumber;
}

Функция встроенных свойств C #:

public class Element 
{
  public string Symbol { get; set; }     
  public string Name { get; set; }     
  public int AtomicNumber { get; set; }
}

Циклы

Java для каждого цикла:

List<Integer> fibNumbers = Arrays.asList(0, 1, 1, 2, 3, 5, 8, 13);
int count = 0;
for (int element: fibNumbers)
{
    count++;
    System.out.println(String.format("Element #%s: %s", count, element));
}
System.out.println(String.format("Number of elements: %s", count));

C # для каждого цикла:

var fibNumbers = new List<int> { 0, 1, 1, 2, 3, 5, 8, 13 };
int count = 0;
foreach (int element in fibNumbers)
{
    count++;
    Console.WriteLine($"Element #{count}: {element}");
}
Console.WriteLine($"Number of elements: {count}");

Реализация интерфейсов / наследования

Наследование и реализация интерфейсов между двумя языками не сильно различаются. Java использует ключевые слова extends или implements; C # использует синтаксис C ++ (объявление происхождения) B : A для определения наследования.

Определение и реализация интерфейса с методами в Java:

package dev.andymacdonald;


import java.util.ArrayList;
import java.util.List;

interface Fish
{
   void swim();
}

class Salmon implements Fish
{

   public void swim()
   {
      System.out.println("Salmon.Fish");
   }
}

class Cod implements Fish
{
   public void swim()
   {
      System.out.println("Cod.Swim");
   }
}

public class Program
{
   public static void main()
   {
      List<Fish> fishes = new ArrayList<>();
      fishes.add(new Salmon());
      fishes.add(new Cod());

      for (Fish fish : fishes)
      {
         fish.swim();
      }
   }
}

Определение и реализация интерфейса с методами на C #:

using System;
using System.Collections.Generic;
namespace Dev.AndyMacdonald 
{
    interface Fish
    {
        void Swim();
    }
    class Salmon : Fish
    {
        public void Swim()
        {
            Console.WriteLine("Salmon.Fish");
        }
    }
    class Cod : Fish
    {
        public void Swim()
        {
            Console.WriteLine("Cod.Swim");
        }
    }
    class Program
    {
        static void Main()
        {
            List<Fish> fishes = new List<Fish>();
            fishes.Add(new Salmon());
            fishes.Add(new Cod());
            foreach (Fish fish in fishes)
            {
                fish.Swim();
            }
        }
    }
}

Указатели

Проще говоря, Java просто не выполняет указатели, тогда как в C # можно выполнять арифметические операции и манипуляции с указателями.

 unsafe {
  int a = 25;
  int * ptr = &a;
  Console.WriteLine($"Value of pointer is {*ptr}");
}

IDE

Visual Studio

Разработчики C # традиционно и обычно используют Visual Studio IDE. Эта ситуация возникла из-за того, что .NET была технологией с закрытым исходным кодом. Microsoft разработала Visual Studio как универсальный магазин для всего, что связано с .NET.

Java пошла другим путем, с самого начала предлагая разработчикам гораздо больший выбор инструментов. Вот почему существует гораздо больший диапазон IDE для разработки на Java (например, IntelliJ, Eclipse, NetBeans). Постепенно среда для разработчиков .NET изменилась, и с годами было предложено больше IDE и выбор разработчиков.

IntelliJ (Java) - Rider (C #)

Пользователи JetBrains IDE сочтут переход от одной IDE к другой очень плавной, если они решат переключиться на соответствующую JetBrains IDE в технологии, на которую они нацелены. Сочетания клавиш, макет IDE и даже некоторые плагины эквивалентны или сопоставимы - практически одна и та же IDE.

Управление зависимостями

Maven (Java) - NuGet и интерфейс командной строки dotnet (C #)

Maven - это инструмент, отвечающий за управление зависимостями и жизненный цикл создания типичных приложений Java и JVM. Тем не менее, он довольно гибкий, имеет тысячи плагинов и может использоваться для создания приложений на других языках, таких как PHP и JavaScript.

Настраиваемая единица maven - это pom.xml файл, который есть в каждом проекте maven. Для подмодулей проекта можно иметь файл pom для каждого подмодуля, который наследуется от родительского. Maven использует какой-либо удаленный сервер или репозиторий для размещения и получения пакетов.

Файл Maven pom.xml (Java):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>dev.andymacdonald</groupId>
    <artifactId>fish-app</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

На простейшем уровне вы можете протестировать и построить проект Maven с помощью следующей команды:

mvn clean install

И создайте пакет с этим:

mvn clean package

И, наконец, разверните такой пакет:

mvn clean deploy

NuGet выполняет аналогичную, хотя и не идентичную роль в .NET для Maven. NuGet может использовать несколько разных файлов конфигурации, но обычно использует .csproj . Как и Maven, NuGet использует сервер / репозиторий, на котором могут размещаться пакеты.

NuGet .csproj файл:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <AssemblyName>MSBuildSample</AssemblyName>
    <OutputPath>Bin\</OutputPath>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="helloworld.cs" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="MyDependency" version="1.0.0" />
  </ItemGroup>  
  <Target Name="Build">
    <MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" />
    <Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe" />
  </Target>
</Project>

Основная роль NuGet - управление пакетами, создание и развертывание. Разработчики Java заметят, что в нем нет той же концепции этапов сборки, что и в Maven. Кроме того, разработчики .NET не склонны редактировать свои файлы сборки вручную, как разработчики Java с pom.xml файлами, предпочитая вместо этого манипулировать ими в своей среде IDE.

Пакеты можно собирать, упаковывать и развертывать в NuGet с помощью следующих nuget команд:

nuget spec
nuget pack {nuspec file}
nuget push {package file} {apikey} -Source {host url}

Если вы хотите запустить тесты для своего .NET-приложения, вы можете запустить следующую команду dotnet CLI:

dotnet test

Интерфейс командной строки dotnet также может использоваться как оболочка для команд nuget.

Серверы приложений

Apache Tomcat (Java) - IIS (ASP.NET)

Tomcat - это веб-сервер с открытым исходным кодом и контейнер сервлетов от Apache Foundation. Хотя есть много других серверов приложений, широко используемых на Java, это довольно распространенный выбор для большинства компаний, выпускающих корпоративное программное обеспечение. Он работает практически во всех операционных системах (например, Windows, Unix, Linux и Mac OS).

.NET-проекты обычно развертываются на IIS, веб-сервере, который работает только в Windows. Хотя его переносимость ограничена, это довольно популярный выбор для разработчиков Windows из-за простоты использования и простоты, при этом предлагая некоторые расширенные параметры конфигурации.

… Но ждать!

Также существует .NET Core ,, который позволяет разрабатывать кроссплатформенные приложения, не ограничиваясь только Windows.

Для веб-приложений .NET Core вы можете упаковать их для запуска как автономные веб-приложения, что позволит вам запускать их следующим образом:

dotnet <app_assembly>.dll

Таким же образом вы можете запустить приложение Java Spring Boot web (которое имеет автономный сервер Tomcat):

java -jar <my-application>.jar

И посетите свое новое блестящее веб-приложение следующим образом:

http://<serveraddress>:<port>

Библиотеки и фреймворки

Spring Framework (Java) - ASP.NET (C #)

Spring Framework - это фреймворк и контейнер IoC для Java. Короче говоря, среда Spring отвечает за создание экземпляров объектов (bean-компонентов) и управление жизненным циклом этих bean-компонентов в памяти.

Создайте ApplicationContext (аналогично концепции Startup в ASP.NET). В этом примере используется Spring Boot:

@SpringBootApplication
public class HumanApplication
{
   public static void main(String[] args) 
   {
      SpringApplication.run(HumanApplication.class, args);
   }
}

Создайте интерфейс:

public interface Organ<T>
{  
   void function();
}

Реализуйте интерфейс Organ<T>:

@Component
public class Heart implements Organ<Heart>
{
    public Heart() {}
    public void function() 
    {
        System.out.println("Buh-dump");
    }
}

Внедрение конструктора списка Organ зависимостей в Human сервис:

@Service
public class Human 
{
    private static final int MAX_SECONDS_OF_LIFE = 3000;
    private List<Organ> organs;
    public Human(List<Organ> organs) 
    {
        this.organs = organs;
    }
    @PostConstruct
    public void live() 
    {
        for (int i = 0; i < MAX_SECONDS_OF_LIFE; i++) 
        {
            organs.forEach(organ -> organ.function());
        }
    }
}

Запустить приложение…

Это aliiiiiiive:

Buh-dump
Buh-dump
Buh-dump
Buh-dump
...

Spring также поставляется с удобным набором модулей и пакетов.

В базовых пакетах Spring и в расширении для фреймворка Spring Boot, предусматривающем обязательную конфигурацию, полезные комбинации существующих и заказных технологий предоставляются разработчикам, желающим получить доступ к общим библиотекам для запуска проекта со всем, что им может понадобиться. чем писать или отслеживать сами эти утилиты:

  • RestTemplate (spring-web - для построения REST и HTTP запросов)
  • JdbcTemplate (spring-data - для построения запросов и операторов JDBC)
  • Spring Security (для создания моделей безопасности приложений и управления ими)
  • ObjectMapper (spring-core - полезная утилита для отображения POJO от Джексона)
  • и т.п.

ASP.NET выполняет аналогичную роль в мире C #, обеспечивая функциональность IoC, широко используемые технологии и утилиты в единой среде. Однако ASP.NET обычно предоставляет функциональность IoC только для веб-приложений, тогда как Spring Framework предоставляет это для любого типа приложения.

Что касается инверсии зависимостей, в ASP.NET можно делать очень похожие вещи, как и в Spring.

Как и раньше, определите необходимый интерфейс и конкретную реализацию:

public interface Organ<T>
{  
   void Function();
}
public class Heart : Organ<Heart>
{
    public Heart() {}
    public void Function() 
    {
        Console.WriteLine("Buh-dump");
    }
}

Вызов функций внедренных зависимостей:

public class Human
{
   private List<IOrgan> _organs;
 
   public Human(List<IOrgan> organs)
   {
      _organs = organs;
      this.Live();
   }
   public void Live()
   {
      organs.ForEach(organ =>
      {
         organ.Function();
      });
   }
}

Определите Startup и зарегистрируйте службы:

public class Startup  
{    
  public void ConfigureServices(IServiceCollection services)
  {    
    services.AddTransient<IList<IOrgan>>(p => p.GetServices<IOrgan>().ToList());
  }
}

ASP.NET также выполняет роль предоставления множества полезных библиотек и утилит для ускорения разработки вашего проекта.

Потоки (Java) - LINQ (C #)

И Java, и C # имеют механизмы для упрощения сокращения наборов данных - Streams и LINQ.

Между двумя технологиями есть некоторые различия и пробелы, но если вы знакомы с одной, вы сможете довольно быстро освоить другую.

Потоки Java:

List<Student> studentList = Arrays.asList( 
    new Student(1, "John", 18, 1),
    new Student(2, "Steve", 21, 1),
);
List<String> studentNames = studentList.stream()
    .filter(s -> s.getAge() > 18)
    .filter(s -> s.getStandardID() > 0)
    .map(s -> s.getName()).collect(Collectors.toList());
studentNames.forEach(name -> System.out.println(name));

Запрос LINQ (C #):

IList<Student> studentList = new List<Student>() { 
    new Student() { StudentID = 1, StudentName = "John", Age = 18, StandardID = 1 } ,
    new Student() { StudentID = 2, StudentName = "Steve",  Age = 21, StandardID = 1 }
};
var studentNames = studentList.Where(s => s.Age > 18)
                        .Where(st => st.StandardID > 0)
                        .Select(s => s.StudentName);
foreach(var name in studentNames) {   
    Console.WriteLine(name);
}

Apache Commons (Java) - CommonLibrary.NET (C #)

Apache Commons предоставляет разработчикам Java набор из нескольких независимо выпущенных полезных компонентов и утилит для ускорения разработки.

Если вам нужна утилита для работы с файлами ZIP или набор утилит для работы с математическими выражениями и формулами, тогда Apache Commons поможет вам.

Аналогичным образом CommonLibrary.NET охватывает и эти основы - есть некоторые ключевые различия в именах некоторых компонентов и модулей, но по большей части они в значительной степени эквивалентны по своему назначению.

Тем не менее, в отличие от Apache Commons, CommonLibrary.NET довольно старая и уже не очень часто используется в проектах. Если вам нужен постоянно обновляемый и тщательно подобранный список библиотек для каждой соответствующей технологии, я настоятельно рекомендую эти два списка:





Библиотеки тестирования

JUnit (Java) - NUnit (C #)

У вечно надежной библиотеки Java JUnit есть прямой эквивалент в C # .

NUnit имеет почти эквивалентную функциональность JUnit и является популярным выбором для разработчиков C #.

JUnit:

@Test
public void complexNumberTest()
{
    ComplexNumber result = someCalculation();
    Assert.assertEquals("Real", 5.2, result.getRealPart());
    Assert.assertEquals("Imaginary" 3.9, result.getImaginaryPart());
}

NUnit:

[Test]
public void ComplexNumberTest()
{
    ComplexNumber result = SomeCalculation();
    Assert.Multiple(() =>
    {
        Assert.AreEqual(5.2, result.RealPart, "Real");
        Assert.AreEqual(3.9, result.ImaginaryPart, "Imaginary");
    });
}

(Ходят слухи, что NUnit начал свою жизнь, когда исходный код JUnit был изменен для работы на C #.)

Mockito (Java) - Moq (C #)

Как и в случае с JUnit и NUnit, сравнимые функциональные возможности существуют между Java Mockito и C # библиотекой Moq.

Мокито:

Foo mockFoo = mock(Foo.class);
when(mockFoo.doSomething("ping")).thenReturn(true);

Moq:

var mock = new Mock<IFoo>();
mock.Setup(foo => foo.DoSomething("ping")).Returns(true);

Это оно

Спасибо за прочтение!

Я, очевидно, не смог вместить в эту статью все различия, сходства и детали - она уже слишком длинная.

Я надеюсь, что, по крайней мере, я прошел достаточно земли, чтобы вы почувствовали себя уверенно, чтобы переключиться и посмотреть, как живет другая половина.