Что такое JAVA?
* Легкий в освоении и простой синтаксис.
Что такое C#?
* C# является частью Microsoft Visual Studio.
... Подходящим примером из реальной жизни будет велосипед — когда мы ездим на нём или меняем деталь, нам не нужно знать, как педаль приводит его в движение или как закреплена цепь.
* C # позволяет использовать компоненты VB NET
C# против Java: основные различия
C# поддерживает перегрузку нескольких операторов. Java по-прежнему не поддерживает перегрузку операторов и указатели. C# может поддерживать лиды только в небезопасном режиме (это не опасно по своей сути, просто код не проверяется CLR). Массивы C # имеют специализацию System, тогда как массивы Java занимаются объектами. Вот чем Java и C# отличаются друг от друга по некоторым ключевым параметрам:
C# против Java: производительность
* Хорошая производительность была мотивом запуска C#. Хорошо известно, что C # использует компилятор Just-in-time, который обычно меньше нагружает ЦП и быстро реагирует.
C# против Java: синтаксис
* Поскольку и C#, и Java следуют за C и C ++, они имеют схожий синтаксис. Объектно-ориентированный - это функция, унаследованная от C ++; поэтому он есть на обоих этих языках.
* Они также обладают схожими характеристиками, такими как сборщик мусора и создание кода промежуточного языка.
* С другой стороны, есть и отличия. Одним из популярных является то, что разработчики C # могут использовать свойства, тогда как Java требует методов get / set вместо свойств. Еще одна проблема заключается в том, что Java имеет встроенную обработку аннотаций, которой нет в C #.
C# против Java: веб-разработка
* Вопрос о том, следует ли вам использовать C# или Java для веб-разработки, зависит от того, какое приложение вы хотите разработать.
* Когда дело доходит до игр, C# - лучший выбор. Вы можете использовать его для разработки приложений Windows, облачных приложений, корпоративного программного обеспечения и многого другого. Такие компании, как Microsoft, Alibaba, Stack Overflow и Intuit, используют C#.
* Язык программирования Java более гибкий, чем C#. Приложения, использующие Java, - это в основном приложения для Android, приложения для центров обработки данных и облачные приложения.
* Google, Netflix, Airbnb, Instagram, Amazon используют Java для целей веб-разработки.
* Итак, в контексте веб-разработки ни один из них не уступает и не превосходит другого.
C# против Java: универсальность
Java используется для сложных приложений, таких как:
* Java используется в веб-приложениях
* В научных приложениях и программном обеспечении
* Используется для создания приложений для Android
* В дата-центрах
* Java поддерживает облачные приложения.
С другой стороны, C # отстает от Java, потому что он использует расширения. Более того, он не оптимизирован для веб-разработки. Тем не менее, если вы собираетесь использовать его для внутриигрового роста и разработки Microsoft, это хороший вариант. Вот несколько приложений, использующих C#:
* Использование в приложениях Windows
C# против Java: безопасность
* Java обеспечивает надежную защиту. Благодаря статистическому набору, он сводит к минимуму ошибки, связанные с типом. Автоматическая проверка кода Java гарантирует, что он будет сохранен прямо перед выполнением. Однако Java немного беспомощен, когда дело касается интегрированных библиотек и приложений.
* С другой стороны, C# уязвим для многих угроз, особенно для инъекций SQL и CMD. Некоторые функции C# в некотором роде являются причинами этих сбоев безопасности. Это не значит, что C# не защищает вашу систему. У него тоже отличная защита, но ее не хватает.
C# против Java: скорость разработки
* Первой целью C # было сделать операционную систему Windows лучшей, а NET Core и .NET 5 показали лучшие результаты. Более того, C# поддерживает повторное использование кода, что внушает благоговение.
* С другой стороны, Java имеет значительное преимущество в стоимости разработки из-за своего синтаксиса. Синтаксис Java не зависит от IDE и любых компиляторов, и он ведет себя одинаково на любой вычислительной платформе.
Справедливо отдать должное обоим языкам программирования за их скорость разработки, потому что важна хорошая команда веб-разработчиков, знающих свой язык программирования наизнанку.
C# против Java: микросервисы
* Microservices Architect - это методология, используемая при разработке для разбиения простого приложения на несколько частей. Каждая часть способна выполнять уникальную функцию сама по себе.
* Когда дело доходит до микросервисов, Java предлагает самые надежные сервисы. Java может создавать сложные приложения, потому что придает большее значение удобочитаемости, что делает ее хорошим вариантом. Более того, компиляторы Java генерируют байт-коды, которые не зависят от компьютерных архитекторов.
* С другой стороны, в C # есть Visual Studio и Mono Develop для предоставления микросервисов. Модели C # более расширяемы и имеют легкие приложения, что делает их хорошим вариантом, но по-прежнему отстает от Java с точки зрения надежности.
Очень часто программисты, пишущие на Java, даже не подозревают о многих (!!!) вещах, которые предоставляет (или, наоборот не предоставляет) C#.
Двинемся дальше и пройдемся по ключевым отличиям и преимуществам.
Сначала мы посмотрим на возможности самих JVM и CLR (Common Language Runtime), далее уже рассмотрим синтаксический структуру C#.
И .NET, и Java используют bytecode. Конечно, кроме самого формата, существует одно очень важное различие – полиморфность.
CIL (Common Intermediate Language, он же MSIL, он же просто IL) – является байт-кодом с полиморфными (обобщенными) инструкциями.
Так, если в Java используется отдельная инструкция для каждого типа операций с различными типами (например: fadd – сложение 2-х float, iadd – сложение 2-х integer), то в CIL для каждого вида операций существует лишь одна инструкция с полиморфными параметрами (например, существует только одна инструкция – add, производящая сложение и float, и integer). Вопрос решения генерации соответствующих x86-инструкций ложится на JIT.
Количество инструкций у обеих платформ примерно одинаковое. Сравнивая список команд байт-кода Java и CIL, видно, что 206 у Java, и 232 — CIL, однако не забываем, что у Java многие команды просто повторяют функционал друг друга.
▌Эпизод III: Generics (parameterized types || parametric polymorphism)
В Java используется механизм type erasure, т.е. поддержка generics обеспечивается лишь компилятором, но не рантаймом, и после компиляции информация о самом типе не будет доступна.
Например, код:
List
List
bool areSame = strList.getClass() == intList.getClass();
System.out.println(areSame);
Выведет true.
При этом вместо обобщенного типа T создается экземпляр объекта типа java.lang.Object.
List
strList.add("stringValue");
list.add("stringValue");
String x = (String) list.get(0);
Таким образом, вся политика безопасности типов разрушается моментально.
.NET, наоборот, имеет полную поддержку generics как compile-time, так и run-time.
Так что же необходимо реализовать для полной поддержки generics в Java? Вместо этого лучше посмотрим, что сделала команда разработчиков .NET’a:
Поддержка generics на уровне Common Type System для кросс-языкового взаимодействия
Полная поддержка со стороны Reflection API
Добавление новых классов/методов в базовые классы (Base Class Library)
Изменения в самом формате и таблицах метаданных
Изменения в алгоритме выделения памяти рантаймом
Добавления новых структур данных
Поддержка generics со стороны JIT (code-sharing)
Изменения в формате CIL (новые инструкции байт-кода)
Поддержка со стороны верификатора CIL-кода
Т.е. generics доступны не только во время компиляции, но и во время исполнения без потери или изменения информации о типе. Также исчезает потребность в boxing/unboxing.
▌Эпизод IV: Types
Java является полностью ОО-языком. С этим можно поспорить. И вот почему: примитивные типы (integer, float и т.п.) не наследуются от java.lang.Object. Поэтому generics в Java не поддерживают primitive types.
А ведь в по-настоящему ОО-языке everything is object.
Это не единственное ограничение. Также невозможно создать собственные примитивные типы.
C# позволяет это делать. Имя этим структурам – struct.
Например:
{
int X1;
int Y1;
}
Также generics в C# позволяют использовать value types (int, float и т.д.)
Если в Java необходимо писать так:
List
Но нельзя так:
List
C# позволяет использование примитивных типов.
Теперь мы подошли к теме иерархии типов в .NET.
В .NET существует 3 вида типов: value, reference и pointer types.
Итак, value type – аналог primitive type из Java. Однако наследуется от System.Object, живет не в куче, а в стеке (а теперь оговорка: расположение value type зависит от его жизненного цикла, например, при участии в замыкании автоматически происходит boxing).
Reference type – представляет собой то же самое, что и reference types в Java.
Pointer type – является самым необычным свойством .NET’a. Дело в том, что CLR позволяет работать с указателями напрямую!
Например:
struct Point
{
public int x;
}
unsafe static void PointerMethod()
{
Point point;
p->x = 100;
p->y = 200;
Point point2;
Point* p2 = &point2;
(*p2).x = 100;
(*p2).y = 200;
}
Очень похоже на C++ код, не так ли?
Сначала определимся, что же умеет C#:
Свойства (в том числе автоматические)
Делегаты
Анонимные методы
Лямбда-выражения
LINQ
Анонимные классы
Мощный вывод типов
Перегрузка операторов
Indexers
…еще много чего
Свойства в C# представляют синтаксический сахар, т.к. при компиляции превращаются в методы типа GetXXX, SetXXX. Однако информация о самом понятии свойство сохраняется в метаданных, поэтому из любого другого поддерживающего свойства языка мы можем обратиться к нему только как object.PropertyX, а не object.GetPropertyX.
Например:
{
public int TotalSum
get
return Count * Price;
}
}
public int Count
{
get;
}
public int Price
{
get
return 50;
}
}
}
{
/*
*весь остальной код
*/
private int
public int Count
{
get { return
}
}
При этом делегаты в .NET – полноценные объекты.
Начиная с появления DLR (Dynamic Language Runtime – основа для динамических языков на .NET), а также dynamic в C# 4 – играет ключевую роль в поддержке динамизма. Для более детального ознакомления советую почитать мою статью Погружаемся в глубины C# dynamic.
Данный подход коренным образом отличается от проекта Da Vinci для Java, т.к. в последнем пытаются расширить саму VM.
Рассмотрим пример на C#:
public class TestClass
{
public delegate int BinaryOp(int arg1, int arg2);
{
return a + b;
{
return first * second;
{
BinaryOp op = new BinaryOp(Add);
Console.WriteLine(result);
//выведет: 3
op = new BinaryOp(Multiply);
result = op(2, 5);
Console.WriteLine(result);
//выведет: 10
}
}
А также на C:
{
return arg1 + arg2;
{
int (*fpAdd)(int, int);
int three = fpAdd(1, 2); // вызываем функцию через указатель
}
Итак, что же мы видим? Если на C мы можем передать указатель на функцию с другими типами параметров (скажем float arg1, float arg2), то в C# — это невозможно. В C# делегаты проходят не только проверку сигнатуры и типов на этапе компиляции, но и в рантайме.
События необходимы для реализации событийно-ориентированного программирования. Конечно, можно обойтись и EventDispatcher’ом, или паттерном Publisher/Subscriber. Однако нативная поддержка со стороны языка дает весомые преимущества. Одним из которых является типобезопасность.
Например:
public class MyClass
{
private string _value;
{
ChangingEventhandler handler = Changing;
handler(oldvalue);
}
public string Value
{
get
return _value;
}
set
OnChanging(_value);
_value = value;
}
}
{
MyClass instance = new MyClass();
instance.Value = "new string value";
//будет вызван метод instance_Changing
}
void instance_Changing(string oldValue)
{
Console.WriteLine(oldValue);
}
Анонимные методы существенно упрощают жизнь – структура класса остается чистой, т.е. не нужно создавать отдельные лишние методы в самом классе.
Изменим вышеприведенный пример с бинарными операциями с использованием анонимных методов:
public class TestClass
{
public delegate int BinaryOp(int arg1, int arg2);
{
BinaryOp op = new BinaryOp(delegate(int a, int b)
return a + b;
});
int result = op(1, 2);
//выведет: 3
}
}
что более коротко и чисто.
{
public delegate int BinaryOp(int arg1, int arg2);
{
BinaryOp op = new BinaryOp((a, b) => a + b);
Console.WriteLine(result);
//выведет: 3
}
}
{
/*
*/
public void TestEvent()
{
MyClass instance = new MyClass();
instance.Value = "new string value";
//будет вызван Console.WriteLine
}
}
{
public void MapReduceTest()
var words = new[] {"...some text goes here..."};
var wordOccurrences = words
.GroupBy(w => w)
.Select(intermediate => new
{
Word = intermediate.Key,
})
.Where(w => w.Frequency > 10)
}
}
{
string[] words = new string[]
"...some text goes here..."
};
var wordOccurrences =
group w by w
into intermediate
select new
{
Word = intermediate.Key,
}
into w
orderby w.Frequency
select w;
}
В этом примере мы видим и LINQ (GroupBy().Select().Where() и т.д.), и анонимные классы –
{
Word = intermediate.Key,
}
Что еще здесь используется? Ответ прост – мощная система вывода типов.
Так без вывода типов нам пришлось бы писать так:
{
string[] words = new string[] { "...some text goes here..." };
return w;
}), delegate (IGrouping
return new { Word = intermediate.Key, Frequency = Enumerable.Sum
}), delegate (<>f__AnonymousType0
return w.Frequency > 10;
}), delegate (<>f__AnonymousType0
return w.Frequency;
}
[Данный метод сгенерировал за нас компилятор]