Розробники C #, які вивчають Java, які найбільші відмінності можна не помітити? [зачинено]


87

Для розробників c #, які прагнуть вивчити Java, чи є якісь основні відмінності між двома мовами, на які слід вказати?

Можливо, деякі люди можуть вважати, що речі однакові, але є деякі аспекти імпорту, які не слід залишати без уваги? (або ви дійсно можете зіпсувати!)

Можливо, з точки зору конструкцій ООП, способу роботи GC, посилань, розгортання тощо.




Також, найімовірніше, залишаться поза увагою наші власні "Приховані особливості C #" stackoverflow.com/questions/9033/hidden-features-of-c
John K

Відповіді:


122

Кілька проблем з маківкою:

  • Java не має власних типів значень (структур), тому не турбуйтеся їх пошуком
  • Перелічення Java сильно відрізняються від підходу "іменованих чисел" у C #; вони більше ОО. Їх можна використовувати з великим ефектом, якщо ви будете обережні.
  • byte підписано на Java (на жаль)
  • У C # ініціалізатори змінних екземпляра виконуються до того, як це робить конструктор базового класу; в Java вони запускаються після цього (тобто безпосередньо перед тілом конструктора в класі "this")
  • У C # методи за замовчуванням запечатані. У Java вони за замовчуванням віртуальні.
  • Модифікатор доступу за замовчуванням у C # - це завжди "найбільш обмежений доступ, доступний у поточному контексті"; в Java це "пакетний" доступ. (Варто прочитати про конкретні модифікатори доступу в Java.)
  • Вкладені типи в Java та C # працюють дещо інакше; зокрема, вони мають різні обмеження доступу, і якщо ви не оголосите вкладений тип таким, staticвін матиме неявне посилання на екземпляр класу, що містить.

5
+1 Це чудовий список для початківців.
Джим Шуберт

3
@ Джон Скіт: +1, і ви б, напевно, сумували за Лямбдою та LINQ до Java 7?
Кб.

1
"У C # ініціалізатори змінних екземпляра виконуються до того, як це робить конструктор базового класу; в Java вони запускаються після цього (тобто безпосередньо перед тілом конструктора в" цьому "класі)" - Eeer, чи можете ви це детальніше описати? Не впевнений, що я насправді розумію, про що ви говорите :)
поміняйте місцями

7
@cwap: У C # порядок виконання - "ініціалізатори змінних екземплярів, конструктор базового класу, тіло конструктора". У Java це "конструктор суперкласу, ініціалізатори змінних екземплярів, тіло конструктора". (Ініціалізатори змінних екземпляра - це те, що ви отримуєте, коли присвоюєте значення змінної екземпляра в точці оголошення.)
Джон Скіт

1
@cwap: Так, це я маю на увазі - останній є ініціалізатором об’єкта .
Джон Скіт,


17

Мене дивує те, що ніхто не згадував властивості, щось цілком фундаментальне в C #, але відсутнє в Java. C # 3 і вище також автоматично реалізували властивості. У Java вам потрібно використовувати методи типу GetX / SetX.

Ще однією очевидною відмінністю є вирази LINQ та лямбда в C # 3, відсутні у Java.

У Java немає декількох простих, але корисних речей, таких як дослівні рядки (@ ""), перевантаження оператора, ітератори з використанням yield та попереднього процесора також відсутні в Java.

Одним з моїх особистих фаворитів у C # є те, що імена простору імен не повинні відповідати фізичній структурі каталогів. Мені дуже подобається ця гнучкість.


10

Є багато відмінностей, але вони мені спадають на думку:

  • Відсутність перевантаження оператора в Java. Слідкуйте за своїм екземпляром. Рівні (екземпляр2) проти екземпляра == екземпляр2 (особливо з рядками).
  • Звикайте, що інтерфейси НЕ мають префікса I. Я часто замість них ви бачите простори імен або класи, суфіксовані Impl.
  • Подвійна перевірка блокування не працює через модель пам'яті Java.
  • Ви можете імпортувати статичні методи, не додаючи їх до імені класу, що дуже корисно в певних випадках (DSL).
  • Оператори перемикання в Java не вимагають за замовчуванням, і ви не можете використовувати рядки як мітки регістрів (IIRC).
  • Загальні засоби для Java розлютять вас. Узагальнені Java не існують під час виконання (принаймні в 1.5), це трюк компілятора, який викликає проблеми, якщо ви хочете задуматися про загальні типи.

4
Востаннє я перевіряв, рядки НЕ перевантажували ==, і я не чув про те, що його додавали для Java 7. Однак вони перевантажують + для конкатенації рядків.
Michael Madsen

3
Так, порівняння рядків з == є дуже поширеною підводною камерою для початківців. .equalsце те, що вам доводиться використовувати.
Майкл Майєрс

Крім того, я не розумію коментар щодо статичних методів. Чи не в усіх мовах дозволені статичні методи чи еквіваленти?
Майкл Майєрс

Я майже висловився за це, але я не згоден з генериками. Мені подобається стирання типу.
finnw

2
"Оператори перемикання в Java не вимагають за замовчуванням" - як і C #.
RenniePet

8

.NET переосмислив дженерики; Java стерла дженерики.

Різниця полягає в наступному: якщо у вас є ArrayList<String>об’єкт у .NET, ви можете сказати (під час виконання), що об’єкт має тип ArrayList<String>, тоді як у Java, під час виконання, об’єкт має тип ArrayList; Stringчастина втрачається. Якщо ви вкладете не- Stringоб'єкти в систему ArrayList, система не зможе застосувати це, і ви дізнаєтесь про це лише після того, як спробуєте витягти елемент, а приведення не вдасться.


1
... хоча варто додати, що ви не можете помістити не- Stringоб'єкти до цього списку, не зробивши де-небудь неперевірений привід , і компілятор буде правильно попереджати вас у той момент, що компілятор більше не може перевіряти загальні межі. Поки ваш список завжди зберігається у змінній List<String>, спроби вставити в нього нерядковий об'єкт не компілюються.
Анджей Дойл

«Нестроковие об'єкти в ArrayList, система не може забезпечити , що": Зверніть увагу , що система робить виконання його під час компіляції. Однак ви можете обійти це, кинувши (або не використовуючи дженерики); тоді перевірка виконання вловить його, але лише під час вилучення.
sleske

1
@Andrzej, @sleske: Я кажу лише про час роботи. Скажімо, ви отримуєте об'єкт за допомогою відображення та викликаєте його addметод (знову ж таки, за допомогою відображення). Чи система відхилить не- Stringоб'єкт відразу, або лише при видачі результату get?
Chris Jester-Young

@sleske: Але IIRC вам потрібен лише неявний привід, щоб обійти перевірку типу.
Нікі

@Judah: Я відкотив ваші зміни (так, через рік після того, як це відбулося), тому що ви не можете мати об'єкти типу List. Ви можете мати об’єкти типів, що походять від List, як ArrayListі LinkedList. (Важливо використовувати Listзамість того, ArrayListщоб передавати їх, але це не змінює той факт, що ви не можете сказати new List().)
Кріс Джестер-Янг

6

Одне, чого мені не вистачає в C # з Java, - це примусова обробка перевірених винятків. У C # далеко не загальноприйнято, що ніхто не знає про винятки, які може створити метод, і ви знаходитесь у владі документації чи тестування, щоб їх виявити. У Java не так, за винятком, що перевірено.


1
FWIW, це було розглянуто у розробці C #, і обгрунтування їхнього відсутності є реальним. Розгляньте artima.com/intv/handcuffs.html . Справа не в тому, що дизайнери філософськи проти перевірених винятків - швидше, вони чекають кращої техніки, яка пропонує подібні переваги без усіх волохатих недоліків.
Greg D

Так, так, дуже суперечлива тема ...
sleske

2
Мені подобається той факт, що в C # немає перевірених винятків, але це було перше повідомлення, яке навіть вказало на різницю, тому +1.
Нік

5

Java має автобоксинг для примітивів, а не для типів значень, тому, хоча System.Int32[]це масив значень у C #, Integer[]є масивом посилань на Integerоб'єкти, і як такий не підходить для більш високих обчислень продуктивності.


1
Піт: це чудовий момент, який я ніколи не знав або, принаймні, ніколи не розглядав (будучи розробником C # та новим для Java).
Джим Шуберт,

4

Ніяких делегатів та подій - вам потрібно використовувати інтерфейси. На щастя, ви можете створювати класи та реалізації інтерфейсу вбудовано, тому це не така вже й велика проблема


3
"не така вже й велика справа". Правильно. Тому що x => x.Fooпроти new Bar() { public void M(SomeType x) { return x.Foo; } }- кому цікаво, щоб код був у 10 разів коротшим?
Kirk Woll

2

Вбудована функція дати / календаря в Java жахлива порівняно з System.DateTime. Тут є багато інформації про це: Що поганого в Java Date & Time API?

Деякі з них можна придбати для розробника C #:

  • Клас Java Date є змінним, що може зробити небезпечними дати повернення та передачі.
  • Більшість конструкторів java.util.Date застаріли. Просто інстантування дати є досить багатослівним.
  • Я ніколи не отримував клас java.util.Date, щоб добре взаємодіяти з веб-службами. У більшості випадків дати з обох сторін дико трансформувались в інші дати та час.

Крім того, Java не має всіх тих самих функцій, які приносять GAC та суворо названі збірки. Jar Hell - це поняття того, що може піти не так при зв’язуванні / посиланні на зовнішні бібліотеки.

Що стосується упаковки / розгортання:

  • може бути важко упакувати веб-програми у форматі EAR / WAR, які фактично встановлюються та працюють на декількох різних серверах додатків (Glassfish, Websphere тощо).
  • розгортання вашої програми Java як служби Windows вимагає набагато більше зусиль, ніж у C #. Більшість рекомендацій, які я отримав щодо цього, стосувалися невільної сторонній бібліотеки
  • конфігурація програми не настільки проста, як включення файлу app.config у ваш проект. Існує клас java.util.Properties, але він не такий надійний, і пошук потрібного місця для видалення файлу .properties може заплутати

1

У Java немає делегатів. Тому, крім усіх переваг, які приносять делегати, заходи також працюють по-різному. Замість того, щоб просто підключити метод, вам потрібно реалізувати інтерфейс і приєднати його.


1

Одна річ, яка вибиває б / к, це в моєму списку інтерв’ю, полягає в тому, що в Java немає "нового" аналога ключового слова для приховування методів, і тому жодного попереджувача компілятора "ви повинні помістити тут нове". Випадковий метод приховування, коли ви хотіли перевизначити, призводить до помилок.

(редагувати, наприклад) Приклад, B походить від A (використовуючи синтаксис C #, Java поводиться так само, як і останній раз, коли я перевірив, але не видає попередження компілятора). Викликається А-фу або Б-Ф? (A викликається, мабуть, дивуючи розробнику, який реалізував B).

class A 
{
public void foo() {code}
}

class B:A
{
public void foo() {code}
}    

void SomeMethod()
{
A a = new B(); // variable's type is declared as A, but assigned to an object of B.
a.foo();
}

2
Як випадково приховати метод екземпляра в Java? вони або остаточні - отже, немає перевизначення чи newметоду навмисного приховування - або не остаточні, так замінені, а не приховані.
Піт Кіркхем

Доданий приклад. Я давно не тестував його на Java, але запитання про інтерв'ю спочатку надходило від групи Java моєї попередньої компанії. У C # попередження компілятора зазвичай означає, що люди змінюють ім'я. Я визнаю, це досить дивний випадок, але ОП, здавалося, просив про речі, які було б потенційно важко знайти при переключенні мов.
Jim L

1
Відмінність тут полягає в тому, що в Java усі методи є віртуальними (тому в Java це буде викликати B.foo (), оскільки Java завжди робить динамічну диспетчеризацію методів), тоді як у C # методи за замовчуванням не віртуальні (і A.foo () буде називатися). Багато засобів перевірки стилів кодування для Java повідомлять вам, що B повинен використовувати анотацію @Override.
Вільям Біллінгслі,

1

У Java немає LINQ, а документація - бісова. Користувальницькі інтерфейси в Java важко розробляти, ви втрачаєте все хороше, що дала нам Microsoft (WPF, WCF тощо), але отримуєте важкі у користуванні, навряд чи задокументовані "API".


0

Одне питання, з яким я стикався до цього часу під час роботи з Java, що надходить із C #, - це винятки та помилки різні.

Наприклад, ви не можете виявити помилку, яка закінчилася, за допомогою catch (виняток e).

Докладніше див. Нижче:

чому-це-java-lang-outofmemoryerror-java-heap-space-not-caught


Він навмисно розроблений таким чином, щоб перешкодити програмісту застосувати його
finnw

Так, я впевнений, що це було, але, виходячи зі сторони C #, де все, про що вам потрібно турбуватися, це вловлювання винятків, кинув мене на цикл :)
Кріс Персічетті

0

Це було так давно, як я був на Java, але те, що я відразу помітив у розробці додатків, - це модель подій C #, перетягування та # перетягування проти використання менеджерів макетів в Swing (якщо ви робите програму App) та обробка винятків з Java, переконавшись, що ви виявили виняток, а C # не потрібно.


0

У відповідь на ваше цілком пряме запитання у вашому заголовку:

"Розробники C #, які вивчають Java, які найбільші відмінності можна не помітити?"

В: Той факт, що Java значно повільніша у Windows.


4
Я запускаю OpenSuSE 64bit і Windows 7 64bit, і Eclipse IDE (здається) швидший в Windows. Ваша відповідь базується на особистих спостереженнях або на реальних орієнтирах?
Джим Шуберт,

0

Найбільш прикрою різницю для мене, коли я переходжу на java, це оголошення рядків.

в C # string(більшу частину часу) на JavaString

Це досить просто, але, повірте, це змушує вас втрачати стільки часу, коли у вас є звичка цього sне робити S!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.