diff --git a/core/lib/Drupal/Core/Entity/EntityFormController.php b/core/lib/Drupal/Core/Entity/EntityFormController.php
index 7c5f7ed..79dc7f4 100644
--- a/core/lib/Drupal/Core/Entity/EntityFormController.php
+++ b/core/lib/Drupal/Core/Entity/EntityFormController.php
@@ -372,13 +372,13 @@ protected function submitEntityLanguage(array $form, array &$form_state) {
       $current_langcode = $entity->language()->langcode == $form_langcode ? $form_state['values']['langcode'] : $form_langcode;
 
       foreach (field_info_instances($entity_type, $entity->bundle()) as $instance) {
-        $field_name = $instance['field_name'];
+        $field_name = $instance->getFieldName();
         $field = field_info_field($field_name);
         $previous_langcode = $form[$field_name]['#language'];
 
         // Handle a possible language change: new language values are inserted,
         // previous ones are deleted.
-        if ($field['translatable'] && $previous_langcode != $current_langcode) {
+        if ($field->translatable && $previous_langcode != $current_langcode) {
           $form_state['values'][$field_name][$current_langcode] = $form_state['values'][$field_name][$previous_langcode];
           $form_state['values'][$field_name][$previous_langcode] = array();
         }
diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockFieldTest.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockFieldTest.php
index da5ac4f..00f575c 100644
--- a/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockFieldTest.php
+++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockFieldTest.php
@@ -80,12 +80,12 @@ public function testBlockFields() {
     ));
     $this->instance->save();
     entity_get_form_display('custom_block', 'link', 'default')
-      ->setComponent($this->field['field_name'], array(
+      ->setComponent($this->field->id(), array(
         'type' => 'link_default',
       ))
       ->save();
     entity_get_display('custom_block', 'link', 'default')
-      ->setComponent($this->field['field_name'], array(
+      ->setComponent($this->field->id(), array(
         'type' => 'link',
         'label' => 'hidden',
       ))
@@ -95,8 +95,8 @@ public function testBlockFields() {
     $this->drupalGet('block/add/link');
     $edit = array(
       'info' => $this->randomName(8),
-      $this->field['field_name'] . '[und][0][url]' => 'http://example.com',
-      $this->field['field_name'] . '[und][0][title]' => 'Example.com'
+      $this->field->id() . '[und][0][url]' => 'http://example.com',
+      $this->field->id() . '[und][0][title]' => 'Example.com'
     );
     $this->drupalPost(NULL, $edit, t('Save'));
     // Place the block.
diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockTypeTest.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockTypeTest.php
index 35f4b98..6d9adb8 100644
--- a/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockTypeTest.php
+++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockTypeTest.php
@@ -79,7 +79,7 @@ public function testCustomBlockTypeEditing() {
     $this->createCustomBlockType('other');
 
     $instance = field_info_instance('custom_block', 'block_body', 'basic');
-    $this->assertEqual($instance['label'], 'Block body', 'Body field was found.');
+    $this->assertEqual($instance->label(), 'Block body', 'Body field was found.');
 
     // Verify that title and body fields are displayed.
     $this->drupalGet('block/add/basic');
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentLanguageTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentLanguageTest.php
index 47efe82..d2d2639 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentLanguageTest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentLanguageTest.php
@@ -72,8 +72,9 @@ function setUp() {
 
     // Make comment body translatable.
     $field = field_info_field('comment_body');
-    $field['translatable'] = TRUE;
+    $field->translatable = TRUE;
     $field->save();
+
     $this->assertTrue(field_is_translatable('comment', $field), 'Comment body is translatable.');
   }
 
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentTranslationUITest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentTranslationUITest.php
index 2a14791..d09e2b6 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentTranslationUITest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentTranslationUITest.php
@@ -64,7 +64,7 @@ protected function getTranslatorPermissions() {
   function setupTestFields() {
     parent::setupTestFields();
     $field = field_info_field('comment_body');
-    $field['translatable'] = TRUE;
+    $field->translatable = TRUE;
     $field->save();
   }
 
diff --git a/core/modules/datetime/datetime.module b/core/modules/datetime/datetime.module
index 88e6a77..5f87276 100644
--- a/core/modules/datetime/datetime.module
+++ b/core/modules/datetime/datetime.module
@@ -116,7 +116,7 @@ function datetime_field_info() {
  * Implements hook_field_settings_form().
  */
 function datetime_field_settings_form($field, $instance) {
-  $settings = $field['settings'];
+  $settings = $field->settings;
 
   $form['datetime_type'] = array(
     '#type' => 'select',
@@ -135,7 +135,7 @@ function datetime_field_settings_form($field, $instance) {
  * Implements hook_field_instance_settings_form().
  */
 function datetime_field_instance_settings_form($field, $instance) {
-  $settings = $instance['settings'];
+  $settings = $instance->settings;
 
   $form['default_value'] = array(
     '#type' => 'select',
@@ -239,7 +239,7 @@ function datetime_field_load($entity_type, $entities, $field, $instances, $langc
       $items[$id][$delta]['date'] = NULL;
       $value = isset($item['value']) ? $item['value'] : NULL;
       if (!empty($value)) {
-        $storage_format = $field['settings']['datetime_type'] == 'date' ? DATETIME_DATE_STORAGE_FORMAT: DATETIME_DATETIME_STORAGE_FORMAT;
+        $storage_format = $field->settings['datetime_type'] == 'date' ? DATETIME_DATE_STORAGE_FORMAT: DATETIME_DATETIME_STORAGE_FORMAT;
         $date = new DrupalDateTime($value, DATETIME_STORAGE_TIMEZONE, $storage_format);
         if ($date instanceOf DrupalDateTime && !$date->hasErrors()) {
           $items[$id][$delta]['date'] = $date;
@@ -252,7 +252,7 @@ function datetime_field_load($entity_type, $entities, $field, $instances, $langc
 /**
  * Sets a default value for an empty date field.
  *
- * Callback for $instance['default_value_function'], as implemented by
+ * Callback for $instance->default_value_function, as implemented by
  * Drupal\datetime\Plugin\field\widget\DateTimeDatepicker.
  *
  * @param $entity_type
@@ -273,11 +273,11 @@ function datetime_default_value($entity, $field, $instance, $langcode) {
 
   $value = '';
   $date = '';
-  if ($instance['settings']['default_value'] == 'now') {
+  if ($instance->settings['default_value'] == 'now') {
     // A default value should be in the format and timezone used for date
     // storage.
     $date = new DrupalDateTime('now', DATETIME_STORAGE_TIMEZONE);
-    $storage_format = $field['settings']['datetime_type'] == 'date' ? DATETIME_DATE_STORAGE_FORMAT: DATETIME_DATETIME_STORAGE_FORMAT;
+    $storage_format = $field->settings['datetime_type'] == 'date' ? DATETIME_DATE_STORAGE_FORMAT: DATETIME_DATETIME_STORAGE_FORMAT;
     $value = $date->format($storage_format);
   }
 
diff --git a/core/modules/edit/lib/Drupal/edit/Form/EditFieldForm.php b/core/modules/edit/lib/Drupal/edit/Form/EditFieldForm.php
index c075b4c..7d52ae0 100644
--- a/core/modules/edit/lib/Drupal/edit/Form/EditFieldForm.php
+++ b/core/modules/edit/lib/Drupal/edit/Form/EditFieldForm.php
@@ -106,7 +106,7 @@ protected function buildEntity(array $form, array &$form_state) {
     //   types: http://drupal.org/node/1678002.
     if ($entity->entityType() == 'node' && $entity->isNewRevision() && !isset($entity->log)) {
       $instance = field_info_instance($entity->entityType(), $form_state['field_name'], $entity->bundle());
-      $entity->log = t('Updated the %field-name field through in-place editing.', array('%field-name' => $instance['label']));
+      $entity->log = t('Updated the %field-name field through in-place editing.', array('%field-name' => $instance->label()));
     }
 
     return $entity;
diff --git a/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php b/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php
index cecc676..e6c77c5 100644
--- a/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php
+++ b/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php
@@ -59,7 +59,7 @@ public function __construct(EditEntityFieldAccessCheckInterface $access_checker,
    * Implements \Drupal\edit\MetadataGeneratorInterface::generate().
    */
   public function generate(EntityInterface $entity, FieldInstance $instance, $langcode, $view_mode) {
-    $field_name = $instance['field_name'];
+    $field_name = $instance->getFieldName();
 
     // Early-return if user does not have access.
     $access = $this->accessChecker->accessEditEntityField($entity, $field_name);
@@ -68,7 +68,7 @@ public function generate(EntityInterface $entity, FieldInstance $instance, $lang
     }
 
     // Early-return if no editor is available.
-    $formatter_id = entity_get_render_display($entity, $view_mode)->getFormatter($instance['field_name'])->getPluginId();
+    $formatter_id = entity_get_render_display($entity, $view_mode)->getFormatter($instance->getFieldName())->getPluginId();
     $items = $entity->getTranslation($langcode, FALSE)->get($field_name)->getValue();
     $editor_id = $this->editorSelector->getEditor($formatter_id, $instance, $items);
     if (!isset($editor_id)) {
@@ -76,7 +76,7 @@ public function generate(EntityInterface $entity, FieldInstance $instance, $lang
     }
 
     // Gather metadata, allow the editor to add additional metadata of its own.
-    $label = $instance['label'];
+    $label = $instance->label();
     $editor = $this->editorManager->createInstance($editor_id);
     $metadata = array(
       'label' => check_plain($label),
diff --git a/core/modules/edit/lib/Drupal/edit/Plugin/InPlaceEditor/DirectEditor.php b/core/modules/edit/lib/Drupal/edit/Plugin/InPlaceEditor/DirectEditor.php
index 39176d1..82f5be3 100644
--- a/core/modules/edit/lib/Drupal/edit/Plugin/InPlaceEditor/DirectEditor.php
+++ b/core/modules/edit/lib/Drupal/edit/Plugin/InPlaceEditor/DirectEditor.php
@@ -27,14 +27,14 @@ class DirectEditor extends EditorBase {
    *   how to generalize to other textual field types.
    */
   function isCompatible(FieldInstance $instance, array $items) {
-    $field = field_info_field($instance['field_name']);
+    $field = field_info_field($instance->getFieldName());
 
     // This editor is incompatible with multivalued fields.
-    if ($field['cardinality'] != 1) {
+    if ($field->cardinality != 1) {
       return FALSE;
     }
     // This editor is incompatible with processed ("rich") text fields.
-    elseif (!empty($instance['settings']['text_processing'])) {
+    elseif (!empty($instance->settings['text_processing'])) {
       return FALSE;
     }
     else {
diff --git a/core/modules/edit/tests/modules/lib/Drupal/edit_test/Plugin/InPlaceEditor/WysiwygEditor.php b/core/modules/edit/tests/modules/lib/Drupal/edit_test/Plugin/InPlaceEditor/WysiwygEditor.php
index 59fe895..44a777d 100644
--- a/core/modules/edit/tests/modules/lib/Drupal/edit_test/Plugin/InPlaceEditor/WysiwygEditor.php
+++ b/core/modules/edit/tests/modules/lib/Drupal/edit_test/Plugin/InPlaceEditor/WysiwygEditor.php
@@ -25,16 +25,16 @@ class WysiwygEditor extends EditorBase {
    * Implements \Drupal\edit\EditPluginInterface::isCompatible().
    */
   function isCompatible(FieldInstance $instance, array $items) {
-    $field = field_info_field($instance['field_name']);
+    $field = field_info_field($instance->getFieldName());
 
     // This editor is incompatible with multivalued fields.
-    if ($field['cardinality'] != 1) {
+    if ($field->cardinality != 1) {
       return FALSE;
     }
     // This editor is compatible with processed ("rich") text fields; but only
     // if there is a currently active text format and that text format is the
     // 'full_html' text format.
-    elseif (!empty($instance['settings']['text_processing'])) {
+    elseif (!empty($instance->settings['text_processing'])) {
       $format_id = $items[0]['format'];
       if (isset($format_id) && $format_id === 'full_html') {
         return TRUE;
diff --git a/core/modules/editor/lib/Drupal/editor/Plugin/InPlaceEditor/Editor.php b/core/modules/editor/lib/Drupal/editor/Plugin/InPlaceEditor/Editor.php
index 7c281c0..9bbcc51 100644
--- a/core/modules/editor/lib/Drupal/editor/Plugin/InPlaceEditor/Editor.php
+++ b/core/modules/editor/lib/Drupal/editor/Plugin/InPlaceEditor/Editor.php
@@ -27,16 +27,16 @@ class Editor extends PluginBase implements EditPluginInterface {
    * Implements \Drupal\edit\Plugin\EditPluginInterface::isCompatible().
    */
   function isCompatible(FieldInstance $instance, array $items) {
-    $field = field_info_field($instance['field_name']);
+    $field = field_info_field($instance->getFieldName());
 
     // This editor is incompatible with multivalued fields.
-    if ($field['cardinality'] != 1) {
+    if ($field->cardinality != 1) {
       return FALSE;
     }
     // This editor is compatible with processed ("rich") text fields; but only
     // if there is a currently active text format, that text format has an
     // associated editor and that editor supports inline editing.
-    elseif (!empty($instance['settings']['text_processing'])) {
+    elseif (!empty($instance->settings['text_processing'])) {
       $format_id = $items[0]['format'];
       if (isset($format_id) && $editor = editor_load($format_id)) {
         $definition = \Drupal::service('plugin.manager.editor')->getDefinition($editor->editor);
diff --git a/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php
index 0a7ff40..a93a091 100644
--- a/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php
+++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php
@@ -220,8 +220,8 @@ public function setComponent($name, array $options = array()) {
     }
 
     if ($instance = field_info_instance($this->targetEntityType, $name, $this->bundle)) {
-      $field = field_info_field($instance['field_name']);
-      $options = $this->pluginManager->prepareConfiguration($field['type'], $options);
+      $field = field_info_field($instance->getFieldName());
+      $options = $this->pluginManager->prepareConfiguration($field->type, $options);
 
       // Clear the persisted plugin, if any.
       unset($this->plugins[$name]);
diff --git a/core/modules/entity_reference/entity_reference.install b/core/modules/entity_reference/entity_reference.install
index c40d3ea..eee8613 100644
--- a/core/modules/entity_reference/entity_reference.install
+++ b/core/modules/entity_reference/entity_reference.install
@@ -32,8 +32,8 @@ function entity_reference_field_schema($field) {
 
   // Create a foreign key to the target entity type base type.
   $entity_manager = Drupal::service('plugin.manager.entity');
-  if (is_subclass_of($entity_manager->getControllerClass($field['settings']['target_type'], 'storage'), 'Drupal\Core\Entity\DatabaseStorageController')) {
-    $entity_info = $entity_manager->getDefinition($field['settings']['target_type']);
+  if (is_subclass_of($entity_manager->getControllerClass($field->settings['target_type'], 'storage'), 'Drupal\Core\Entity\DatabaseStorageController')) {
+    $entity_info = $entity_manager->getDefinition($field->settings['target_type']);
 
     $base_table = $entity_info['base_table'];
     $id_column = $entity_info['entity_keys']['id'];
diff --git a/core/modules/entity_reference/entity_reference.module b/core/modules/entity_reference/entity_reference.module
index 84d4743..4d60243 100644
--- a/core/modules/entity_reference/entity_reference.module
+++ b/core/modules/entity_reference/entity_reference.module
@@ -51,14 +51,14 @@ function entity_reference_entity_field_info_alter(&$info, $entity_type) {
   foreach (field_info_instances($entity_type) as $bundle_name => $instances) {
     foreach ($instances as $field_name => $instance) {
       $field = field_info_field($field_name);
-      if ($field['type'] != 'entity_reference') {
+      if ($field->type != 'entity_reference') {
         continue;
       }
       if (isset($info['definitions'][$field_name])) {
-        $info['definitions'][$field_name]['settings']['target_type'] = $field['settings']['target_type'];
+        $info['definitions'][$field_name]['settings']['target_type'] = $field->settings['target_type'];
       }
       elseif (isset($info['optional'][$field_name])) {
-        $info['optional'][$field_name]['settings']['target_type'] = $field['settings']['target_type'];
+        $info['optional'][$field_name]['settings']['target_type'] = $field->settings['target_type'];
       }
     }
   }
@@ -131,9 +131,9 @@ function entity_reference_field_validate(EntityInterface $entity = NULL, $field,
     $invalid_entities = array_diff_key($ids, array_flip($valid_ids));
     if ($invalid_entities) {
       foreach ($invalid_entities as $id => $delta) {
-        $errors[$field['field_name']][$langcode][$delta][] = array(
+        $errors[$field->id()][$langcode][$delta][] = array(
           'error' => 'entity_reference_invalid_entity',
-          'message' => t('The referenced entity (@type: @id) does not exist.', array('@type' => $field['settings']['target_type'], '@id' => $id)),
+          'message' => t('The referenced entity (@type: @id) does not exist.', array('@type' => $field->settings['target_type'], '@id' => $id)),
         );
       }
     }
@@ -159,7 +159,7 @@ function entity_reference_field_settings_form($field, $instance) {
     '#type' => 'select',
     '#title' => t('Type of item to reference'),
     '#options' => $entity_type_options,
-    '#default_value' => $field['settings']['target_type'],
+    '#default_value' => $field->settings['target_type'],
     '#required' => TRUE,
     '#disabled' => $field->hasData(),
     '#size' => 1,
@@ -174,24 +174,24 @@ function entity_reference_field_settings_form($field, $instance) {
  * Reset the instance handler settings, when the target type is changed.
  */
 function entity_reference_field_update_field($field, $prior_field) {
-  if ($field['type'] != 'entity_reference') {
+  if ($field->type != 'entity_reference') {
     // Not an entity reference field.
     return;
   }
 
-  if ($field['settings']['target_type'] == $prior_field['settings']['target_type']) {
+  if ($field->settings['target_type'] == $prior_field->settings['target_type']) {
     // Target type didn't change.
     return;
   }
 
-  if (empty($field['bundles'])) {
+  if ($field->getBundles() == array()) {
     // Field has no instances.
     return;
   }
 
-  $field_name = $field['field_name'];
+  $field_name = $field->id();
 
-  foreach ($field['bundles'] as $entity_type => $bundles) {
+  foreach ($field->getBundles() as $entity_type => $bundles) {
     foreach ($bundles as $bundle) {
       $instance = field_info_instance($entity_type, $field_name, $bundle);
       $instance->settings['handler_settings'] = array();
@@ -207,11 +207,11 @@ function entity_reference_field_instance_settings_form($field, $instance, $form_
   $field = isset($form_state['entity_reference']['field']) ? $form_state['entity_reference']['field'] : $field;
   $instance = isset($form_state['entity_reference']['instance']) ? $form_state['entity_reference']['instance'] : $instance;
 
-  $settings = $instance['settings'];
+  $settings = $instance->settings;
   $settings += array('handler' => 'default');
 
   // Get all selection plugins for this entity type.
-  $selection_plugins = Drupal::service('plugin.manager.entity_reference.selection')->getSelectionGroups($field['settings']['target_type']);
+  $selection_plugins = Drupal::service('plugin.manager.entity_reference.selection')->getSelectionGroups($field->settings['target_type']);
   $handler_groups = array_keys($selection_plugins);
 
   $handlers = Drupal::service('plugin.manager.entity_reference.selection')->getDefinitions();
@@ -334,7 +334,7 @@ function _entity_reference_element_validate_filter(&$element, &$form_state) {
 function _entity_reference_field_instance_settings_validate($form, &$form_state) {
   $instance = $form['#instance'];
   if (isset($form_state['values']['instance'])) {
-    $instance['settings'] = $form_state['values']['instance']['settings'];
+    $instance->settings = $form_state['values']['instance']['settings'];
   }
   $form_state['entity_reference']['instance'] = $instance;
 
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceAutocomplete.php b/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceAutocomplete.php
index 6a42b57..14f89e9 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceAutocomplete.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceAutocomplete.php
@@ -60,7 +60,7 @@ public function __construct(EntityManager $entity_manager) {
    * @see \Drupal\entity_reference\EntityReferenceController
    */
   public function getMatches($field, $instance, $entity_type, $entity_id = '', $prefix = '', $string = '') {
-    $target_type = $field['settings']['target_type'];
+    $target_type = $field->settings['target_type'];
     $matches = array();
     $entity = NULL;
 
@@ -75,7 +75,7 @@ public function getMatches($field, $instance, $entity_type, $entity_id = '', $pr
 
     if (isset($string)) {
       // Get an array of matching entities.
-      $widget = entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')->getComponent($instance['field_name']);
+      $widget = entity_get_form_display($instance->entity_type, $instance->bundle, 'default')->getComponent($instance->getFieldName());
       $match_operator = !empty($widget['settings']['match_operator']) ? $widget['settings']['match_operator'] : 'CONTAINS';
       $entity_labels = $handler->getReferencableEntities($string, $match_operator, 10);
 
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceController.php b/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceController.php
index b6099f1..252e301 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceController.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceController.php
@@ -77,7 +77,7 @@ public function handleAutocomplete(Request $request, $type, $field_name, $entity
       throw new AccessDeniedHttpException();
     }
 
-    if ($field['type'] != 'entity_reference' || !field_access('edit', $field, $entity_type)) {
+    if ($field->type != 'entity_reference' || !field_access('edit', $field, $entity_type)) {
       throw new AccessDeniedHttpException();
     }
 
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/SelectionBase.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/SelectionBase.php
index 97aeb6e..b306475 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/SelectionBase.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/SelectionBase.php
@@ -56,14 +56,14 @@ public function __construct(FieldDefinitionInterface $field_definition, EntityIn
    * Implements SelectionInterface::settingsForm().
    */
   public static function settingsForm(&$field, &$instance) {
-    $entity_info = entity_get_info($field['settings']['target_type']);
-    $bundles = entity_get_bundles($field['settings']['target_type']);
+    $entity_info = entity_get_info($field->settings['target_type']);
+    $bundles = entity_get_bundles($field->settings['target_type']);
 
     // Merge-in default values.
-    if (!isset($instance['settings']['handler_settings'])) {
-      $instance['settings']['handler_settings'] = array();
+    if (!isset($instance->settings['handler_settings'])) {
+      $instance->settings['handler_settings'] = array();
     }
-    $instance['settings']['handler_settings'] += array(
+    $instance->settings['handler_settings'] += array(
       'target_bundles' => array(),
       'sort' => array(
         'field' => '_none',
@@ -79,10 +79,10 @@ public static function settingsForm(&$field, &$instance) {
 
       $target_bundles_title = t('Bundles');
       // Default core entity types with sensible labels.
-      if ($field['settings']['target_type'] == 'node') {
+      if ($field->settings['target_type'] == 'node') {
         $target_bundles_title = t('Content types');
       }
-      elseif ($field['settings']['target_type'] == 'taxonomy_term') {
+      elseif ($field->settings['target_type'] == 'taxonomy_term') {
         $target_bundles_title = t('Vocabularies');
       }
 
@@ -90,7 +90,7 @@ public static function settingsForm(&$field, &$instance) {
         '#type' => 'checkboxes',
         '#title' => $target_bundles_title,
         '#options' => $bundle_options,
-        '#default_value' => (!empty($instance['settings']['handler_settings']['target_bundles'])) ? $instance['settings']['handler_settings']['target_bundles'] : array(),
+        '#default_value' => (!empty($instance->settings['handler_settings']['target_bundles'])) ? $instance->settings['handler_settings']['target_bundles'] : array(),
         '#required' => TRUE,
         '#size' => 6,
         '#multiple' => TRUE,
@@ -107,7 +107,7 @@ public static function settingsForm(&$field, &$instance) {
     // @todo Use Entity::getPropertyDefinitions() when all entity types are
     // converted to the new Field API.
     $fields = drupal_map_assoc(drupal_schema_fields_sql($entity_info['base_table']));
-    foreach (field_info_instances($field['settings']['target_type']) as $bundle_instances) {
+    foreach (field_info_instances($field->settings['target_type']) as $bundle_instances) {
       foreach ($bundle_instances as $instance_name => $instance_info) {
         $field_info = field_info_field($instance_name);
         foreach ($field_info['columns'] as $column_name => $column_info) {
@@ -124,7 +124,7 @@ public static function settingsForm(&$field, &$instance) {
       ) + $fields,
       '#ajax' => TRUE,
       '#limit_validation_errors' => array(),
-      '#default_value' => $instance['settings']['handler_settings']['sort']['field'],
+      '#default_value' => $instance->settings['handler_settings']['sort']['field'],
     );
 
     $form['sort']['settings'] = array(
@@ -133,9 +133,9 @@ public static function settingsForm(&$field, &$instance) {
       '#process' => array('_entity_reference_form_process_merge_parent'),
     );
 
-    if ($instance['settings']['handler_settings']['sort']['field'] != '_none') {
+    if ($instance->settings['handler_settings']['sort']['field'] != '_none') {
       // Merge-in default values.
-      $instance['settings']['handler_settings']['sort'] += array(
+      $instance->settings['handler_settings']['sort'] += array(
         'direction' => 'ASC',
       );
 
@@ -147,7 +147,7 @@ public static function settingsForm(&$field, &$instance) {
           'ASC' => t('Ascending'),
           'DESC' => t('Descending'),
         ),
-        '#default_value' => $instance['settings']['handler_settings']['sort']['direction'],
+        '#default_value' => $instance->settings['handler_settings']['sort']['direction'],
       );
     }
 
@@ -261,8 +261,8 @@ public function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') {
     $entity_info = entity_get_info($target_type);
 
     $query = \Drupal::entityQuery($target_type);
-    if (!empty($this->instance['settings']['handler_settings']['target_bundles'])) {
-      $query->condition($entity_info['entity_keys']['bundle'], $this->instance['settings']['handler_settings']['target_bundles'], 'IN');
+    if (!empty($this->instance->settings['handler_settings']['target_bundles'])) {
+      $query->condition($entity_info['entity_keys']['bundle'], $this->instance->settings['handler_settings']['target_bundles'], 'IN');
     }
 
     if (isset($match) && isset($entity_info['entity_keys']['label'])) {
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceFormatterBase.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceFormatterBase.php
index 51f5285..5c4a252 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceFormatterBase.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceFormatterBase.php
@@ -40,7 +40,7 @@ public function prepareView(array $entities, $langcode, array &$items) {
       }
     }
 
-    $target_type = $this->field['settings']['target_type'];
+    $target_type = $this->field->settings['target_type'];
 
     $target_entities = array();
 
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceItemTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceItemTest.php
index 8c17fd6..4539f13 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceItemTest.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceItemTest.php
@@ -119,7 +119,7 @@ public function testEntityReferenceFieldSchema() {
     $this->assertEqual(count($schema['foreign keys']), 1, 'There is 1 foreign key in the schema.');
 
     $foreign_key = reset($schema['foreign keys']);
-    $foreign_key_column = _field_sql_storage_columnname($field['field_name'], $foreign_key_column_name);
+    $foreign_key_column = _field_sql_storage_columnname($field->id(), $foreign_key_column_name);
     $this->assertEqual($foreign_key['table'], 'taxonomy_term_data', 'Foreign key table name preserved in the schema.');
     $this->assertEqual($foreign_key['columns'][$foreign_key_column], 'tid', 'Foreign key column name preserved in the schema.');
 
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionSortTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionSortTest.php
index 09dd2c8..6592f27 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionSortTest.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionSortTest.php
@@ -133,7 +133,7 @@ public function testSort() {
     $this->assertIdentical($result['article'], $expected_result, 'Query sorted by field returned expected values.');
 
     // Assert sort by property.
-    $instance['settings']['handler_settings']['sort'] = array(
+    $instance->settings['handler_settings']['sort'] = array(
       'field' => 'nid',
       'direction' => 'ASC',
     );
diff --git a/core/modules/field/field.api.php b/core/modules/field/field.api.php
index 3535b00..e8256ea 100644
--- a/core/modules/field/field.api.php
+++ b/core/modules/field/field.api.php
@@ -237,7 +237,7 @@ function hook_field_info_alter(&$info) {
  *     as related, only existing SQL tables, such as {taxonomy_term_data}.
  */
 function hook_field_schema($field) {
-  if ($field['type'] == 'text_long') {
+  if ($field->type == 'text_long') {
     $columns = array(
       'value' => array(
         'type' => 'text',
@@ -250,7 +250,7 @@ function hook_field_schema($field) {
     $columns = array(
       'value' => array(
         'type' => 'varchar',
-        'length' => $field['settings']['max_length'],
+        'length' => $field->settings['max_length'],
         'not null' => FALSE,
       ),
     );
@@ -320,7 +320,7 @@ function hook_field_load($entity_type, $entities, $field, $instances, $langcode,
       // by formatters if needed.
       if (empty($instances[$id]['settings']['text_processing']) || filter_format_allowcache($item['format'])) {
         $items[$id][$delta]['safe_value'] = isset($item['value']) ? text_sanitize($instances[$id]['settings']['text_processing'], $langcode, $item, 'value') : '';
-        if ($field['type'] == 'text_with_summary') {
+        if ($field->type == 'text_with_summary') {
           $items[$id][$delta]['safe_summary'] = isset($item['summary']) ? text_sanitize($instances[$id]['settings']['text_processing'], $langcode, $item, 'summary') : '';
         }
       }
@@ -355,14 +355,14 @@ function hook_field_load($entity_type, $entities, $field, $instances, $langcode,
  * @param $langcode
  *   The language associated with $items.
  * @param $items
- *   $entity->{$field['field_name']}, or an empty array if unset.
+ *   $entity->{$field->id()}, or an empty array if unset.
  */
 function hook_field_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items) {
   // Sample code from image.module: if there are no images specified at all,
   // use the default image.
   foreach ($entities as $id => $entity) {
-    if (empty($items[$id]) && $field['settings']['default_image']) {
-      if ($file = file_load($field['settings']['default_image'])) {
+    if (empty($items[$id]) && $field->settings['default_image']) {
+      if ($file = file_load($field->settings['default_image'])) {
         $items[$id][0] = (array) $file + array(
           'is_default' => TRUE,
           'alt' => '',
@@ -388,7 +388,7 @@ function hook_field_prepare_view($entity_type, $entities, $field, $instances, $l
  * @param $langcode
  *   The language associated with $items.
  * @param $items
- *   $entity->{$field['field_name']}[$langcode], or an empty array if unset.
+ *   $entity->{$field->id()}[$langcode], or an empty array if unset.
  * @param $errors
  *   The array of errors (keyed by field name, language code, and delta) that
  *   have already been reported for the entity. The function should add its
@@ -400,10 +400,10 @@ function hook_field_prepare_view($entity_type, $entities, $field, $instances, $l
 function hook_field_validate(\Drupal\Core\Entity\EntityInterface $entity = NULL, $field, $instance, $langcode, $items, &$errors) {
   foreach ($items as $delta => $item) {
     if (!empty($item['value'])) {
-      if (!empty($field['settings']['max_length']) && drupal_strlen($item['value']) > $field['settings']['max_length']) {
-        $errors[$field['field_name']][$langcode][$delta][] = array(
+      if (!empty($field->settings['max_length']) && drupal_strlen($item['value']) > $field->settings['max_length']) {
+        $errors[$field->id()][$langcode][$delta][] = array(
           'error' => 'text_max_length',
-          'message' => t('%name: the value may not be longer than %max characters.', array('%name' => $instance['label'], '%max' => $field['settings']['max_length'])),
+          'message' => t('%name: the value may not be longer than %max characters.', array('%name' => $instance->label(), '%max' => $field->settings['max_length'])),
         );
       }
     }
@@ -425,15 +425,15 @@ function hook_field_validate(\Drupal\Core\Entity\EntityInterface $entity = NULL,
  * @param $langcode
  *   The language associated with $items.
  * @param $items
- *   $entity->{$field['field_name']}[$langcode], or an empty array if unset.
+ *   $entity->{$field->id()}[$langcode], or an empty array if unset.
  */
 function hook_field_presave(\Drupal\Core\Entity\EntityInterface $entity, $field, $instance, $langcode, &$items) {
-  if ($field['type'] == 'number_decimal') {
+  if ($field->type == 'number_decimal') {
     // Let PHP round the value to ensure consistent behavior across storage
     // backends.
     foreach ($items as $delta => $item) {
       if (isset($item['value'])) {
-        $items[$delta]['value'] = round($item['value'], $field['settings']['scale']);
+        $items[$delta]['value'] = round($item['value'], $field->settings['scale']);
       }
     }
   }
@@ -458,13 +458,13 @@ function hook_field_presave(\Drupal\Core\Entity\EntityInterface $entity, $field,
  * @param $langcode
  *   The language associated with $items.
  * @param $items
- *   $entity->{$field['field_name']}[$langcode], or an empty array if unset.
+ *   $entity->{$field->id()}[$langcode], or an empty array if unset.
  *
  * @see hook_field_update()
  * @see hook_field_delete()
  */
 function hook_field_insert(\Drupal\Core\Entity\EntityInterface $entity, $field, $instance, $langcode, &$items) {
-  if (config('taxonomy.settings')->get('maintain_index_table') && $field['storage']['type'] == 'field_sql_storage' && $entity->entityType() == 'node' && $entity->status) {
+  if (config('taxonomy.settings')->get('maintain_index_table') && $field->storage['type'] == 'field_sql_storage' && $entity->entityType() == 'node' && $entity->status) {
     $query = db_insert('taxonomy_index')->fields(array('nid', 'tid', 'sticky', 'created', ));
     foreach ($items as $item) {
       $query->values(array(
@@ -497,13 +497,13 @@ function hook_field_insert(\Drupal\Core\Entity\EntityInterface $entity, $field,
  * @param $langcode
  *   The language associated with $items.
  * @param $items
- *   $entity->{$field['field_name']}[$langcode], or an empty array if unset.
+ *   $entity->{$field->id()}[$langcode], or an empty array if unset.
  *
  * @see hook_field_insert()
  * @see hook_field_delete()
  */
 function hook_field_update(\Drupal\Core\Entity\EntityInterface $entity, $field, $instance, $langcode, &$items) {
-  if (config('taxonomy.settings')->get('maintain_index_table') && $field['storage']['type'] == 'field_sql_storage' && $entity->entityType() == 'node') {
+  if (config('taxonomy.settings')->get('maintain_index_table') && $field->storage['type'] == 'field_sql_storage' && $entity->entityType() == 'node') {
     $first_call = &drupal_static(__FUNCTION__, array());
 
     // We don't maintain data for old revisions, so clear all previous values
@@ -581,7 +581,7 @@ function hook_field_storage_update_field($field, $prior_field) {
  * @param $langcode
  *   The language associated with $items.
  * @param $items
- *   $entity->{$field['field_name']}[$langcode], or an empty array if unset.
+ *   $entity->{$field->id()}[$langcode], or an empty array if unset.
  *
  * @see hook_field_insert()
  * @see hook_field_update()
@@ -609,7 +609,7 @@ function hook_field_delete(\Drupal\Core\Entity\EntityInterface $entity, $field,
  * @param $langcode
  *   The language associated with $items.
  * @param $items
- *   $entity->{$field['field_name']}[$langcode], or an empty array if unset.
+ *   $entity->{$field->id()}[$langcode], or an empty array if unset.
  */
 function hook_field_delete_revision(\Drupal\Core\Entity\EntityInterface $entity, $field, $instance, $langcode, &$items) {
   foreach ($items as $delta => $item) {
@@ -630,7 +630,7 @@ function hook_field_delete_revision(\Drupal\Core\Entity\EntityInterface $entity,
  * @param $langcode
  *   The language associated with $items.
  * @param $items
- *   $entity->{$field['field_name']}[$langcode], or an empty array if unset.
+ *   $entity->{$field->id()}[$langcode], or an empty array if unset.
  * @param $source_entity
  *   The source entity from which field values are being copied.
  * @param $source_langcode
@@ -639,7 +639,7 @@ function hook_field_delete_revision(\Drupal\Core\Entity\EntityInterface $entity,
 function hook_field_prepare_translation(\Drupal\Core\Entity\EntityInterface $entity, $field, $instance, $langcode, &$items, $source_entity, $source_langcode) {
   // If the translating user is not permitted to use the assigned text format,
   // we must not expose the source values.
-  $field_name = $field['field_name'];
+  $field_name = $field->id();
   $formats = filter_formats();
   $format_id = $source_entity->{$field_name}[$source_langcode][0]['format'];
   if (!filter_access($formats[$format_id])) {
@@ -1196,8 +1196,8 @@ function hook_field_storage_details($field) {
   $details = array();
 
   // Add field columns.
-  foreach ((array) $field['columns'] as $column_name => $attributes) {
-    $real_name = _field_sql_storage_columnname($field['field_name'], $column_name);
+  foreach ((array) $field->getSchema('columns') as $column_name => $attributes) {
+    $real_name = _field_sql_storage_columnname($field->id(), $column_name);
     $columns[$column_name] = $real_name;
   }
   return array(
@@ -1224,9 +1224,9 @@ function hook_field_storage_details($field) {
  * @see hook_field_storage_details()
  */
 function hook_field_storage_details_alter(&$details, $field) {
-  if ($field['field_name'] == 'field_of_interest') {
+  if ($field->id() == 'field_of_interest') {
     $columns = array();
-    foreach ((array) $field['columns'] as $column_name => $attributes) {
+    foreach ((array) $field->getSchema('columns') as $column_name => $attributes) {
       $columns[$column_name] = $column_name;
     }
     $details['drupal_variables'] = array(
@@ -1274,7 +1274,7 @@ function hook_field_storage_load($entity_type, $entities, $age, $fields, $option
     // on each field individually is more efficient than loading all fields in
     // memory upfront with field_info_field_by_ids().
     $field = field_info_field_by_id($field_id);
-    $field_name = $field['field_name'];
+    $field_name = $field->id();
     $table = $load_current ? _field_sql_storage_tablename($field) : _field_sql_storage_revision_tablename($field);
 
     $query = db_select($table, 't')
@@ -1296,11 +1296,11 @@ function hook_field_storage_load($entity_type, $entities, $age, $fields, $option
         $delta_count[$row->entity_id][$row->langcode] = 0;
       }
 
-      if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$row->langcode] < $field['cardinality']) {
+      if ($field->cardinality == FIELD_CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$row->langcode] < $field->cardinality) {
         $item = array();
         // For each column declared by the field, populate the item
         // from the prefixed database column.
-        foreach ($field['columns'] as $column => $attributes) {
+        foreach ($field->getSchema('columns') as $column => $attributes) {
           $column_name = _field_sql_storage_columnname($field_name, $column);
           $item[$column] = $row->$column_name;
         }
@@ -1338,7 +1338,7 @@ function hook_field_storage_write(\Drupal\Core\Entity\EntityInterface $entity, $
 
   foreach ($fields as $field_id) {
     $field = field_info_field_by_id($field_id);
-    $field_name = $field['field_name'];
+    $field_name = $field->id();
     $table_name = _field_sql_storage_tablename($field);
     $revision_name = _field_sql_storage_revision_tablename($field);
 
@@ -1368,7 +1368,7 @@ function hook_field_storage_write(\Drupal\Core\Entity\EntityInterface $entity, $
     // Prepare the multi-insert query.
     $do_insert = FALSE;
     $columns = array('entity_type', 'entity_id', 'revision_id', 'bundle', 'delta', 'langcode');
-    foreach ($field['columns'] as $column => $attributes) {
+    foreach ($field->getSchema('columns') as $column => $attributes) {
       $columns[] = _field_sql_storage_columnname($field_name, $column);
     }
     $query = db_insert($table_name)->fields($columns);
@@ -1388,7 +1388,7 @@ function hook_field_storage_write(\Drupal\Core\Entity\EntityInterface $entity, $
           'delta' => $delta,
           'langcode' => $langcode,
         );
-        foreach ($field['columns'] as $column => $attributes) {
+        foreach ($field->getSchema('columns') as $column => $attributes) {
           $record[_field_sql_storage_columnname($field_name, $column)] = isset($item[$column]) ? $item[$column] : NULL;
         }
         $query->values($record);
@@ -1396,7 +1396,7 @@ function hook_field_storage_write(\Drupal\Core\Entity\EntityInterface $entity, $
           $revision_query->values($record);
         }
 
-        if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED && ++$delta_count == $field['cardinality']) {
+        if ($field->cardinality != FIELD_CARDINALITY_UNLIMITED && ++$delta_count == $field->cardinality) {
           break;
         }
       }
@@ -1424,8 +1424,8 @@ function hook_field_storage_write(\Drupal\Core\Entity\EntityInterface $entity, $
  */
 function hook_field_storage_delete(\Drupal\Core\Entity\EntityInterface $entity, $fields) {
   foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) {
-    if (isset($fields[$instance['field_id']])) {
-      $field = field_info_field_by_id($instance['field_id']);
+    if (isset($fields[$instance->field_uuid])) {
+      $field = field_info_field_by_id($instance->field_uuid);
       field_sql_storage_field_storage_purge($entity, $field, $instance);
     }
   }
@@ -1502,7 +1502,7 @@ function hook_field_storage_query($query) {
       $select_query->fields($table_alias, array('entity_type', 'entity_id', 'revision_id', 'bundle'));
       $field_base_table = $table_alias;
     }
-    if ($field['cardinality'] != 1) {
+    if ($field->cardinality != 1) {
       $select_query->distinct();
     }
   }
@@ -1512,7 +1512,7 @@ function hook_field_storage_query($query) {
     $table_alias = $table_aliases[$key];
     $field = $condition['field'];
     // Add the specified condition.
-    $sql_field = "$table_alias." . _field_sql_storage_columnname($field['field_name'], $condition['column']);
+    $sql_field = "$table_alias." . _field_sql_storage_columnname($field->id(), $condition['column']);
     $query->addCondition($select_query, $sql_field, $condition);
     // Add delta / language group conditions.
     foreach (array('delta', 'langcode') as $column) {
@@ -1565,7 +1565,7 @@ function hook_field_storage_query($query) {
       $specifier = $order['specifier'];
       $field = $specifier['field'];
       $table_alias = $table_aliases[$specifier['index']];
-      $sql_field = "$table_alias." . _field_sql_storage_columnname($field['field_name'], $specifier['column']);
+      $sql_field = "$table_alias." . _field_sql_storage_columnname($field->id(), $specifier['column']);
       $select_query->orderBy($sql_field, $order['direction']);
     }
     elseif ($order['type'] == 'property') {
@@ -1605,7 +1605,7 @@ function hook_field_storage_create_field($field) {
  */
 function hook_field_storage_delete_field($field) {
   // Mark all data associated with the field for deletion.
-  $field['deleted'] = FALSE;
+  $field->deleted = FALSE;
   $table = _field_sql_storage_tablename($field);
   $revision_table = _field_sql_storage_revision_tablename($field);
   db_update($table)
@@ -1613,7 +1613,7 @@ function hook_field_storage_delete_field($field) {
     ->execute();
 
   // Move the table to a unique name while the table contents are being deleted.
-  $field['deleted'] = TRUE;
+  $field->deleted = TRUE;
   $new_table = _field_sql_storage_tablename($field);
   $revision_new_table = _field_sql_storage_revision_tablename($field);
   db_rename_table($table, $new_table);
@@ -1632,18 +1632,18 @@ function hook_field_storage_delete_field($field) {
  *   The instance being deleted.
  */
 function hook_field_storage_delete_instance($instance) {
-  $field = field_info_field($instance['field_name']);
+  $field = field_info_field($instance->getFieldName());
   $table_name = _field_sql_storage_tablename($field);
   $revision_name = _field_sql_storage_revision_tablename($field);
   db_update($table_name)
     ->fields(array('deleted' => 1))
-    ->condition('entity_type', $instance['entity_type'])
-    ->condition('bundle', $instance['bundle'])
+    ->condition('entity_type', $instance->entity_type)
+    ->condition('bundle', $instance->bundle)
     ->execute();
   db_update($revision_name)
     ->fields(array('deleted' => 1))
-    ->condition('entity_type', $instance['entity_type'])
-    ->condition('bundle', $instance['bundle'])
+    ->condition('entity_type', $instance->entity_type)
+    ->condition('bundle', $instance->bundle)
     ->execute();
 }
 
@@ -1857,13 +1857,13 @@ function hook_field_update_forbid($field, $prior_field) {
   // the new field will have fewer values, and any data exists for the
   // abandoned keys, the field will have no way to display them. So,
   // forbid such an update.
-  if ($field->hasData() && count($field['settings']['allowed_values']) < count($prior_field['settings']['allowed_values'])) {
+  if ($field->hasData() && count($field->settings['allowed_values']) < count($prior_field->settings['allowed_values'])) {
     // Identify the keys that will be lost.
-    $lost_keys = array_diff(array_keys($field['settings']['allowed_values']), array_keys($prior_field['settings']['allowed_values']));
+    $lost_keys = array_diff(array_keys($field->settings['allowed_values']), array_keys($prior_field->settings['allowed_values']));
     // If any data exist for those keys, forbid the update.
     $query = new EntityFieldQuery();
     $found = $query
-      ->fieldCondition($prior_field['field_name'], 'value', $lost_keys)
+      ->fieldCondition($prior_field->id(), 'value', $lost_keys)
       ->range(0, 1)
       ->execute();
     if ($found) {
@@ -1969,7 +1969,7 @@ function hook_field_read_instance($instance) {
  */
 function hook_field_purge_field($field) {
   db_delete('my_module_field_info')
-    ->condition('id', $field['id'])
+    ->condition('id', $field->id())
     ->execute();
 }
 
@@ -1987,7 +1987,7 @@ function hook_field_purge_field($field) {
  */
 function hook_field_purge_instance($instance) {
   db_delete('my_module_field_instance_info')
-    ->condition('id', $instance['id'])
+    ->condition('id', $instance->id)
     ->execute();
 }
 
@@ -2018,7 +2018,7 @@ function hook_field_storage_purge_field($field) {
  */
 function hook_field_storage_purge_field_instance($instance) {
   db_delete('my_module_field_instance_info')
-    ->condition('id', $instance['id'])
+    ->condition('id', $instance->id)
     ->execute();
 }
 
@@ -2073,7 +2073,7 @@ function hook_field_storage_purge(\Drupal\Core\Entity\EntityInterface $entity, $
  *   TRUE if the operation is allowed, and FALSE if the operation is denied.
  */
 function hook_field_access($op, \Drupal\field\FieldInterface $field, $entity_type, $entity, $account) {
-  if ($field['field_name'] == 'field_of_interest' && $op == 'edit') {
+  if ($field->id() == 'field_of_interest' && $op == 'edit') {
     return user_access('edit field of interest', $account);
   }
   return TRUE;
diff --git a/core/modules/field/field.attach.inc b/core/modules/field/field.attach.inc
index 7965679..f49eeb8 100644
--- a/core/modules/field/field.attach.inc
+++ b/core/modules/field/field.attach.inc
@@ -171,8 +171,8 @@ function field_invoke_method($method, $target_function, EntityInterface $entity,
     $target = call_user_func($target_function, $instance);
 
     if (method_exists($target, $method)) {
-      $field = field_info_field_by_id($instance['field_id']);
-      $field_name = $field['field_name'];
+      $field = field_info_field_by_id($instance->field_uuid);
+      $field_name = $field->id();
 
       // Determine the list of languages to iterate on.
       $available_langcodes = field_available_languages($entity_type, $field);
@@ -266,8 +266,8 @@ function field_invoke_method_multiple($method, $target_function, array $entities
     $entity_instances = _field_invoke_get_instances($entity_type, $entity->bundle(), $options);
 
     foreach ($entity_instances as $instance) {
-      $instance_id = $instance['id'];
-      $field_name = $instance['field_name'];
+      $instance_id = $instance->id;
+      $field_name = $instance->getFieldName();
 
       // Let the closure determine the target object on which the method should
       // be called.
@@ -283,7 +283,7 @@ function field_invoke_method_multiple($method, $target_function, array $entities
 
         // Unless a language code suggestion is provided we iterate on all the
         // available language codes.
-        $field = field_info_field_by_id($instance['field_id']);
+        $field = field_info_field_by_id($instance->field_uuid);
         $available_langcodes = field_available_languages($entity_type, $field);
         $langcode = !empty($options['langcode'][$id]) ? $options['langcode'][$id] : $options['langcode'];
         $langcodes = _field_language_suggestion($available_langcodes, $langcode, $field_name);
@@ -300,7 +300,7 @@ function field_invoke_method_multiple($method, $target_function, array $entities
 
   // For each instance, invoke the method and collect results.
   foreach ($instances as $instance_id => $instance) {
-    $field_name = $instance['field_name'];
+    $field_name = $instance->getFieldName();
 
     // Iterate over all the field translations.
     foreach ($grouped_items[$instance_id] as $langcode => &$items) {
@@ -401,9 +401,9 @@ function _field_invoke($op, EntityInterface $entity, &$a = NULL, &$b = NULL, $op
   foreach ($instances as $instance) {
     // field_info_field() is not available for deleted fields, so use
     // field_info_field_by_id().
-    $field = field_info_field_by_id($instance['field_id']);
-    $field_name = $field['field_name'];
-    $function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op;
+    $field = field_info_field_by_id($instance->field_uuid);
+    $field_name = $field->id();
+    $function = $options['default'] ? 'field_default_' . $op : $field->module . '_field_' . $op;
     if (function_exists($function)) {
       // Determine the list of languages to iterate on.
       $available_langcodes = field_available_languages($entity->entityType(), $field);
@@ -509,10 +509,10 @@ function _field_invoke_multiple($op, $entity_type, $entities, &$a = NULL, &$b =
     $id = $entity->id();
 
     foreach ($instances as $instance) {
-      $field_id = $instance['field_id'];
-      $field_name = $instance['field_name'];
+      $field_id = $instance->field_uuid;
+      $field_name = $instance->getFieldName();
       $field = field_info_field_by_id($field_id);
-      $function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op;
+      $function = $options['default'] ? 'field_default_' . $op : $field->module . '_field_' . $op;
       if (function_exists($function)) {
         // Add the field to the list of fields to invoke the hook on.
         if (!isset($fields[$field_id])) {
@@ -540,8 +540,8 @@ function _field_invoke_multiple($op, $entity_type, $entities, &$a = NULL, &$b =
 
   // For each field, invoke the field hook and collect results.
   foreach ($fields as $field_id => $field) {
-    $field_name = $field['field_name'];
-    $function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op;
+    $field_name = $field->id();
+    $function = $options['default'] ? 'field_default_' . $op : $field->module . '_field_' . $op;
     // Iterate over all the field translations.
     foreach ($grouped_items[$field_id] as $langcode => &$items) {
       $entities = $grouped_entities[$field_id][$langcode];
@@ -671,11 +671,11 @@ function _field_invoke_get_instances($entity_type, $bundle, $options) {
     // Deleted fields are not included in field_info_instances(), and need to
     // be fetched from the database with field_read_instances().
     $params = array('entity_type' => $entity_type, 'bundle' => $bundle);
-    if (isset($options['field_id'])) {
+    if (isset($options->field_uuid)) {
       // Single-field mode by field id: field_read_instances() does the filtering.
       // Single-field mode by field name is not compatible with the 'deleted'
       // option.
-      $params['field_id'] = $options['field_id'];
+      $params->field_uuid = $options->field_uuid;
     }
     $instances = field_read_instances($params, array('include_deleted' => TRUE));
   }
@@ -686,11 +686,11 @@ function _field_invoke_get_instances($entity_type, $bundle, $options) {
   }
   else {
     $instances = field_info_instances($entity_type, $bundle);
-    if (isset($options['field_id'])) {
+    if (isset($options->field_uuid)) {
       // Single-field mode by field id: we need to loop on each instance to
       // find the right one.
       foreach ($instances as $instance) {
-        if ($instance['field_id'] == $options['field_id']) {
+        if ($instance->field_uuid == $options->field_uuid) {
           $instances = array($instance);
           break;
         }
@@ -714,7 +714,7 @@ function _field_invoke_get_instances($entity_type, $bundle, $options) {
  */
 function _field_invoke_widget_target($form_display) {
   return function ($instance) use ($form_display) {
-    return $form_display->getWidget($instance['field_name']);
+    return $form_display->getWidget($instance->getFieldName());
   };
 }
 
@@ -893,7 +893,7 @@ function field_attach_load($entity_type, $entities, $age = FIELD_LOAD_CURRENT, $
   // types can be cached.
   $cache_read = $load_current && $info['field_cache'] && empty($options['deleted']);
   // In addition, do not write to the cache when loading a single field.
-  $cache_write = $cache_read && !isset($options['field_id']);
+  $cache_write = $cache_read && !isset($options->field_uuid);
 
   if (empty($entities)) {
     return;
@@ -954,8 +954,8 @@ function field_attach_load($entity_type, $entities, $age = FIELD_LOAD_CURRENT, $
       $id = $entity->id();
       $vid = $entity->getRevisionId();
       foreach ($instances as $instance) {
-        $field_name = $instance['field_name'];
-        $field_id = $instance['field_id'];
+        $field_name = $instance->getFieldName();
+        $field_id = $instance->field_uuid;
         // Make sure all fields are present at least as empty arrays.
         if (!isset($queried_entities[$id]->{$field_name})) {
           $queried_entities[$id]->{$field_name} = array();
@@ -963,7 +963,7 @@ function field_attach_load($entity_type, $entities, $age = FIELD_LOAD_CURRENT, $
         // Collect the storage backend if the field has not been loaded yet.
         if (!isset($skip_fields[$field_id])) {
           $field = field_info_field_by_id($field_id);
-          $storages[$field['storage']['type']][$field_id][] = $load_current ? $id : $vid;
+          $storages[$field->storage['type']][$field_id][] = $load_current ? $id : $vid;
         }
       }
     }
@@ -988,7 +988,7 @@ function field_attach_load($entity_type, $entities, $age = FIELD_LOAD_CURRENT, $
         $data = array();
         $instances = field_info_instances($entity_type, $entity->bundle());
         foreach ($instances as $instance) {
-          $data[$instance['field_name']] = $queried_entities[$id]->{$instance['field_name']};
+          $data[$instance->getFieldName()] = $queried_entities[$id]->{$instance->getFieldName()};
         }
         $cid = "field:$entity_type:$id";
         cache('field')->set($cid, $data);
@@ -1198,13 +1198,13 @@ function field_attach_insert(EntityInterface $entity) {
   // Collect the storage backends used by the remaining fields in the entities.
   $storages = array();
   foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) {
-    $field = field_info_field_by_id($instance['field_id']);
-    $field_id = $field['uuid'];
-    $field_name = $field['field_name'];
+    $field = field_info_field_by_id($instance->field_uuid);
+    $field_id = $field->uuid;
+    $field_name = $field->id();
     if (!empty($entity->$field_name)) {
       // Collect the storage backend if the field has not been written yet.
       if (!isset($skip_fields[$field_id])) {
-        $storages[$field['storage']['type']][$field_id] = $field_id;
+        $storages[$field->storage['type']][$field_id] = $field_id;
       }
     }
   }
@@ -1242,9 +1242,9 @@ function field_attach_update(EntityInterface $entity) {
   // Collect the storage backends used by the remaining fields in the entities.
   $storages = array();
   foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) {
-    $field = field_info_field_by_id($instance['field_id']);
-    $field_id = $field['uuid'];
-    $field_name = $field['field_name'];
+    $field = field_info_field_by_id($instance->field_uuid);
+    $field_id = $field->uuid;
+    $field_name = $field->id();
     // Leave the field untouched if $entity comes with no $field_name property,
     // but empty the field if it comes as a NULL value or an empty array.
     // Function property_exists() is slower, so we catch the more frequent
@@ -1252,7 +1252,7 @@ function field_attach_update(EntityInterface $entity) {
     if (isset($entity->$field_name) || property_exists($entity, $field_name)) {
       // Collect the storage backend if the field has not been written yet.
       if (!isset($skip_fields[$field_id])) {
-        $storages[$field['storage']['type']][$field_id] = $field_id;
+        $storages[$field->storage['type']][$field_id] = $field_id;
       }
     }
   }
@@ -1288,9 +1288,9 @@ function field_attach_delete(EntityInterface $entity) {
   // Collect the storage backends used by the fields in the entities.
   $storages = array();
   foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) {
-    $field = field_info_field_by_id($instance['field_id']);
-    $field_id = $field['uuid'];
-    $storages[$field['storage']['type']][$field_id] = $field_id;
+    $field = field_info_field_by_id($instance->field_uuid);
+    $field_id = $field->uuid;
+    $storages[$field->storage['type']][$field_id] = $field_id;
   }
 
   // Field storage backends delete their data.
@@ -1324,9 +1324,9 @@ function field_attach_delete_revision(EntityInterface $entity) {
   // Collect the storage backends used by the fields in the entities.
   $storages = array();
   foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) {
-    $field = field_info_field_by_id($instance['field_id']);
-    $field_id = $field['uuid'];
-    $storages[$field['storage']['type']][$field_id] = $field_id;
+    $field = field_info_field_by_id($instance->field_uuid);
+    $field_id = $field->uuid;
+    $storages[$field->storage['type']][$field_id] = $field_id;
   }
 
   // Field storage backends delete their data.
@@ -1397,8 +1397,8 @@ function field_attach_prepare_view($entity_type, array $entities, array $display
   // instance, call the prepareView() method on the formatter object handed by
   // the entity display.
   $target_function = function ($instance) use ($displays) {
-    if (isset($displays[$instance['bundle']])) {
-      return $displays[$instance['bundle']]->getFormatter($instance['field_name']);
+    if (isset($displays[$instance->bundle])) {
+      return $displays[$instance->bundle]->getFormatter($instance->getFieldName());
     }
   };
   field_invoke_method_multiple('prepareView', $target_function, $prepare, $null, $null, $options);
@@ -1440,7 +1440,7 @@ function field_attach_view(EntityInterface $entity, EntityDisplay $display, $lan
   // For each instance, call the view() method on the formatter object handed
   // by the entity display.
   $target_function = function ($instance) use ($display) {
-    return $display->getFormatter($instance['field_name']);
+    return $display->getFormatter($instance->getFieldName());
   };
   $null = NULL;
   $output = field_invoke_method('view', $target_function, $entity, $null, $null, $options);
@@ -1485,7 +1485,7 @@ function field_attach_preprocess(EntityInterface $entity, $element, &$variables)
   // Ensure we are working with a BC mode entity.
   $entity = $entity->getBCEntity();
   foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) {
-    $field_name = $instance['field_name'];
+    $field_name = $instance->getFieldName();
     if (isset($element[$field_name]['#language'])) {
       $langcode = $element[$field_name]['#language'];
       $variables[$field_name] = isset($entity->{$field_name}[$langcode]) ? $entity->{$field_name}[$langcode] : NULL;
@@ -1554,7 +1554,7 @@ function field_entity_bundle_rename($entity_type, $bundle_old, $bundle_new) {
   $instances = field_read_instances();
   foreach ($instances as $instance) {
     if ($instance->entity_type == $entity_type && $instance->bundle == $bundle_old) {
-      $id_new = $instance['entity_type'] . '.' . $bundle_new . '.' . $instance['field_name'];
+      $id_new = $instance->entity_type . '.' . $bundle_new . '.' . $instance->getFieldName();
       $instance->id = $id_new;
       $instance->bundle = $bundle_new;
       $instance->allowBundleRename();
diff --git a/core/modules/field/field.crud.inc b/core/modules/field/field.crud.inc
index bbd0d45..49c46e3 100644
--- a/core/modules/field/field.crud.inc
+++ b/core/modules/field/field.crud.inc
@@ -78,7 +78,7 @@ function field_create_field(array $field) {
  *
  * @param mixed $field
  *   Either the \Drupal\field\Plugin\Core\Entity\Field object to update, or a
- *   field array structure. If the latter, $field['field_name'] must provided;
+ *   field array structure. If the latter, $field->id() must provided;
  *   it identifies the field that will be updated to match this structure. Any
  *   other properties of the field that are not specified in $field will be left
  *   unchanged, so it is not necessary to pass in a fully populated $field
@@ -93,7 +93,7 @@ function field_create_field(array $field) {
 function field_update_field($field) {
   // Module developers can still pass in an array of properties.
   if (is_array($field)) {
-    $field_loaded = entity_load('field_entity', $field['field_name']);
+    $field_loaded = entity_load('field_entity', $field->id());
     if (empty($field_loaded)) {
       throw new FieldException('Attempt to update a non-existent field.');
     }
@@ -250,7 +250,7 @@ function field_update_instance($instance) {
     }
     // Merge incoming values.
     foreach ($instance as $key => $value) {
-      $instance_loaded[$key] = $value;
+      $instance_loaded->$key = $value;
     }
     $instance = $instance_loaded;
   }
@@ -425,7 +425,7 @@ function field_purge_batch($batch_size) {
   $factory = Drupal::service('entity.query');
   $info = entity_get_info();
   foreach ($instances as $instance) {
-    $entity_type = $instance['entity_type'];
+    $entity_type = $instance->entity_type;
 
     // EntityFieldQuery currently fails on conditions on comment bundle.
     // Remove when http://drupal.org/node/731724 is fixed.
@@ -435,13 +435,13 @@ function field_purge_batch($batch_size) {
 
     $ids = (object) array(
       'entity_type' => $entity_type,
-      'bundle' => $instance['bundle'],
+      'bundle' => $instance->bundle,
     );
     // field_purge_data() will need the field array.
-    $field = field_info_field_by_id($instance['field_id']);
+    $field = field_info_field_by_id($instance->field_uuid);
     // Retrieve some entities.
     $query = $factory->get($entity_type)
-      ->condition('id:' . $field['uuid'] . '.deleted', 1)
+      ->condition('id:' . $field->uuid . '.deleted', 1)
       ->range(0, $batch_size);
     // If there's no bundle key, all results will have the same bundle.
     if (!empty($info[$entity_type]['entity_keys']['bundle'])) {
@@ -459,7 +459,7 @@ function field_purge_batch($batch_size) {
         $ids->entity_id = $entity_id;
         $entities[$entity_id] = _field_create_entity_from_ids($ids);
       }
-      field_attach_load($entity_type, $entities, FIELD_LOAD_CURRENT, array('field_id' => $field['uuid'], 'deleted' => 1));
+      field_attach_load($entity_type, $entities, FIELD_LOAD_CURRENT, array('field_id' => $field->uuid, 'deleted' => 1));
       foreach ($entities as $entity) {
         // Purge the data for the entity.
         field_purge_data($entity, $field, $instance);
@@ -475,7 +475,7 @@ function field_purge_batch($batch_size) {
   $deleted_fields = Drupal::state()->get('field.field.deleted') ?: array();
   foreach ($deleted_fields as $field) {
     $field = new Field($field);
-    $instances = field_read_instances(array('field_id' => $field['uuid']), array('include_deleted' => 1));
+    $instances = field_read_instances(array('field_id' => $field->uuid), array('include_deleted' => 1));
     if (empty($instances)) {
       field_purge_field($field);
     }
@@ -499,11 +499,11 @@ function field_purge_batch($batch_size) {
 function field_purge_data(EntityInterface $entity, $field, $instance) {
   // Each field type's hook_field_delete() only expects to operate on a single
   // field at a time, so we can use it as-is for purging.
-  $options = array('field_id' => $instance['field_id'], 'deleted' => TRUE);
+  $options = array('field_id' => $instance->field_uuid, 'deleted' => TRUE);
   _field_invoke('delete', $entity, $dummy, $dummy, $options);
 
   // Tell the field storage system to purge the data.
-  module_invoke($field['storage']['module'], 'field_storage_purge', $entity, $field, $instance);
+  module_invoke($field->storage['module'], 'field_storage_purge', $entity, $field, $instance);
 
   // Let other modules act on purging the data.
   foreach (module_implements('field_attach_purge') as $module) {
@@ -523,12 +523,12 @@ function field_purge_data(EntityInterface $entity, $field, $instance) {
  */
 function field_purge_instance($instance) {
   // Notify the storage engine.
-  $field = field_info_field_by_id($instance['field_id']);
-  module_invoke($field['storage']['module'], 'field_storage_purge_instance', $instance);
+  $field = field_info_field_by_id($instance->field_uuid);
+  module_invoke($field->storage['module'], 'field_storage_purge_instance', $instance);
 
   $state = Drupal::state();
   $deleted_instances = $state->get('field.instance.deleted');
-  unset($deleted_instances[$instance['uuid']]);
+  unset($deleted_instances[$instance->uuid]);
   $state->set('field.instance.deleted', $deleted_instances);
 
   // Clear the cache.
@@ -548,18 +548,18 @@ function field_purge_instance($instance) {
  *   The field record to purge.
  */
 function field_purge_field($field) {
-  $instances = field_read_instances(array('field_id' => $field['uuid']), array('include_deleted' => 1));
+  $instances = field_read_instances(array('field_id' => $field->uuid), array('include_deleted' => 1));
   if (count($instances) > 0) {
-    throw new FieldException(t('Attempt to purge a field @field_name that still has instances.', array('@field_name' => $field['field_name'])));
+    throw new FieldException(t('Attempt to purge a field @field_name that still has instances.', array('@field_name' => $field->id())));
   }
 
   $state = Drupal::state();
   $deleted_fields = $state->get('field.field.deleted');
-  unset($deleted_fields[$field['uuid']]);
+  unset($deleted_fields[$field->uuid]);
   $state->set('field.field.deleted', $deleted_fields);
 
   // Notify the storage engine.
-  module_invoke($field['storage']['module'], 'field_storage_purge_field', $field);
+  module_invoke($field->storage['module'], 'field_storage_purge_field', $field);
 
   // Clear the cache.
   field_info_cache_clear();
diff --git a/core/modules/field/field.default.inc b/core/modules/field/field.default.inc
index cc6a393..0bcd490 100644
--- a/core/modules/field/field.default.inc
+++ b/core/modules/field/field.default.inc
@@ -31,7 +31,7 @@
  * @param $langcode
  *   The language associated with $items.
  * @param $items
- *   $entity->{$field['field_name']}[$langcode], or an empty array if unset.
+ *   $entity->{$field->id()}[$langcode], or an empty array if unset.
  * @param $errors
  *   The array of errors, keyed by field name and by value delta, that have
  *   already been reported for the entity. The function should add its errors to
@@ -42,15 +42,15 @@
  */
 function field_default_validate(EntityInterface $entity, $field, $instance, $langcode, $items, &$errors) {
   // Filter out empty values.
-  $items = _field_filter_items($field['type'], $items);
+  $items = _field_filter_items($field->type, $items);
 
   // Check that the number of values doesn't exceed the field cardinality.
   // For form submitted values, this can only happen with 'multiple value'
   // widgets.
-  if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED && count($items) > $field['cardinality']) {
-    $errors[$field['field_name']][$langcode][0][] = array(
+  if ($field->cardinality != FIELD_CARDINALITY_UNLIMITED && count($items) > $field->cardinality) {
+    $errors[$field->id()][$langcode][0][] = array(
       'error' => 'field_cardinality',
-      'message' => t('%name: this field cannot hold more than @count values.', array('%name' => $instance['label'], '@count' => $field['cardinality'])),
+      'message' => t('%name: this field cannot hold more than @count values.', array('%name' => $instance->label(), '@count' => $field->cardinality)),
     );
   }
 }
@@ -67,14 +67,14 @@ function field_default_validate(EntityInterface $entity, $field, $instance, $lan
  * @param $langcode
  *   The language the entity has to be translated to.
  * @param $items
- *   $entity->{$field['field_name']}[$langcode], or an empty array if unset.
+ *   $entity->{$field->id()}[$langcode], or an empty array if unset.
  * @param \Drupal\Core\Entity\EntityInterface $source_entity
  *   The source entity holding the field values to be translated.
  * @param $source_langcode
  *   The source language from which to translate.
  */
 function field_default_prepare_translation(EntityInterface $entity, $field, $instance, $langcode, &$items, EntityInterface $source_entity, $source_langcode) {
-  $field_name = $field['field_name'];
+  $field_name = $field->id();
   // If the field is untranslatable keep using Language::LANGCODE_NOT_SPECIFIED.
   if ($langcode == Language::LANGCODE_NOT_SPECIFIED) {
     $source_langcode = Language::LANGCODE_NOT_SPECIFIED;
diff --git a/core/modules/field/field.info.inc b/core/modules/field/field.info.inc
index f69649d..8cecbb2 100644
--- a/core/modules/field/field.info.inc
+++ b/core/modules/field/field.info.inc
@@ -145,7 +145,7 @@ function _field_info_collate_types_reset() {
  */
 function field_behaviors_widget($op, $instance) {
   $info = array();
-  if ($component = entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')->getComponent($instance['field_name'])) {
+  if ($component = entity_get_form_display($instance->entity_type, $instance->bundle, 'default')->getComponent($instance->getFieldName())) {
     $info = field_info_widget_types($component['type']);
   }
   return isset($info[$op]) ? $info[$op] : FIELD_BEHAVIOR_DEFAULT;
@@ -289,8 +289,8 @@ function field_info_fields() {
 
   $fields = array();
   foreach ($info as $key => $field) {
-    if (!$field['deleted']) {
-      $fields[$field['field_name']] = $field;
+    if (!$field->deleted) {
+      $fields[$field->id()] = $field;
     }
   }
 
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index 299ada6..c2809ec 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -208,7 +208,7 @@ function field_system_info_alter(&$info, $file, $type) {
       // remains no actual, non-deleted fields)
       $non_deleted = FALSE;
       foreach ($fields as $field) {
-        if (empty($field['deleted'])) {
+        if (empty($field->deleted)) {
           $non_deleted = TRUE;
           break;
         }
@@ -304,9 +304,9 @@ function field_entity_field_info($entity_type) {
       // @todo: Allow for adding field type settings.
       $definition = array(
         'label' => t('Field !name', array('!name' => $field_name)),
-        'type' => isset($field_types[$field['type']]['data_type']) ? $field_types[$field['type']]['data_type'] :  $field['type'] . '_field',
+        'type' => isset($field_types[$field->type]['data_type']) ? $field_types[$field->type]['data_type'] :  $field->type . '_field',
         'configurable' => TRUE,
-        'translatable' => !empty($field['translatable'])
+        'translatable' => !empty($field->translatable)
       );
 
       if ($optional) {
@@ -489,12 +489,12 @@ function field_sync_field_status() {
  */
 function field_get_default_value(EntityInterface $entity, $field, $instance, $langcode = NULL) {
   $items = array();
-  if (!empty($instance['default_value_function'])) {
-    $function = $instance['default_value_function'];
+  if (!empty($instance->default_value_function)) {
+    $function = $instance->default_value_function;
     $items = $function($entity, $field, $instance, $langcode);
   }
-  elseif (!empty($instance['default_value'])) {
-    $items = $instance['default_value'];
+  elseif (!empty($instance->default_value)) {
+    $items = $instance->default_value;
   }
   return $items;
 }
@@ -535,7 +535,7 @@ function _field_filter_items($field_type, $items) {
  *   The sorted array of field items.
  */
 function _field_sort_items($field, $items) {
-  if (($field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED) && isset($items[0]['_weight'])) {
+  if (($field->cardinality > 1 || $field->cardinality == FIELD_CARDINALITY_UNLIMITED) && isset($items[0]['_weight'])) {
     usort($items, '_field_sort_items_helper');
     foreach ($items as $delta => $item) {
       if (is_array($items[$delta])) {
@@ -808,7 +808,7 @@ function field_view_field(EntityInterface $entity, $field_name, $display_options
     // $display_options, so we cannot let preparation happen internally.
     $field = field_info_field($field_name);
     $formatter_manager = drupal_container()->get('plugin.manager.field.formatter');
-    $display_options = $formatter_manager->prepareConfiguration($field['type'], $display_options);
+    $display_options = $formatter_manager->prepareConfiguration($field->type, $display_options);
     $formatter = $formatter_manager->getInstance(array(
       'field_definition' => $instance,
       'view_mode' => $view_mode,
diff --git a/core/modules/field/field.multilingual.inc b/core/modules/field/field.multilingual.inc
index 6f6e2d6..5863cb1 100644
--- a/core/modules/field/field.multilingual.inc
+++ b/core/modules/field/field.multilingual.inc
@@ -30,7 +30,7 @@
  *
  * The available language codes for a particular field are returned by
  * field_available_languages(). Whether a field is translatable is determined by
- * calling field_is_translatable(), which checks the $field['translatable']
+ * calling field_is_translatable(), which checks the $field->translatable
  * property returned by field_info_field() and whether the entity type the field
  * is attached to supports translation.
  *
@@ -88,7 +88,7 @@ function field_available_languages($entity_type, $field) {
     $drupal_static_fast['field_langcodes'] = &drupal_static(__FUNCTION__);
   }
   $field_langcodes = &$drupal_static_fast['field_langcodes'];
-  $field_name = $field['field_name'];
+  $field_name = $field->id();
 
   if (!isset($field_langcodes[$entity_type][$field_name])) {
     // If the field has language support enabled we retrieve an (alterable) list
@@ -174,7 +174,7 @@ function field_language_fallback_enabled() {
  *   TRUE if the field can be translated.
  */
 function field_is_translatable($entity_type, $field) {
-  return $field['translatable'] && field_has_translation_handler($entity_type);
+  return $field->translatable && field_has_translation_handler($entity_type);
 }
 
 /**
@@ -267,17 +267,17 @@ function field_language(EntityInterface $entity, $field_name = NULL, $langcode =
     // if the field translation is not available. It is up to translation
     // handlers to implement language fallback rules.
     foreach (field_info_instances($entity_type, $bundle) as $instance) {
-      if (isset($entity->{$instance['field_name']}[$langcode])) {
-        $display_langcode[$instance['field_name']] = $langcode;
+      if (isset($entity->{$instance->getFieldName()}[$langcode])) {
+        $display_langcode[$instance->getFieldName()] = $langcode;
       }
       else {
         // If the field has a value for one of the locked languages, then use
         // that language for display. If not, the default one will be
         // Language::LANGCODE_NOT_SPECIFIED.
-        $display_langcode[$instance['field_name']] = Language::LANGCODE_NOT_SPECIFIED;
+        $display_langcode[$instance->getFieldName()] = Language::LANGCODE_NOT_SPECIFIED;
         foreach (language_list(Language::STATE_LOCKED) as $language_locked) {
-          if (isset($entity->{$instance['field_name']}[$language_locked->langcode])) {
-            $display_langcode[$instance['field_name']] = $language_locked->langcode;
+          if (isset($entity->{$instance->getFieldName()}[$language_locked->langcode])) {
+            $display_langcode[$instance->getFieldName()] = $language_locked->langcode;
             break;
           }
         }
diff --git a/core/modules/field/field.views.inc b/core/modules/field/field.views.inc
index 5a1f4f3..6b2efe9 100644
--- a/core/modules/field/field.views.inc
+++ b/core/modules/field/field.views.inc
@@ -18,11 +18,11 @@
 function field_views_data() {
   $data = array();
   foreach (field_info_fields() as $field) {
-    if ($field['storage']['type'] != 'field_sql_storage') {
+    if ($field->storage['type'] != 'field_sql_storage') {
       continue;
     }
 
-    $module = $field['module'];
+    $module = $field->module;
     $result = (array) module_invoke($module, 'field_views_data', $field);
 
     if (empty($result)) {
@@ -48,11 +48,11 @@ function field_views_data() {
  */
 function field_views_data_alter(&$data) {
   foreach (field_info_fields() as $field) {
-    if ($field['storage']['type'] != 'field_sql_storage') {
+    if ($field->storage['type'] != 'field_sql_storage') {
       continue;
     }
 
-    $function = $field['module'] . '_field_views_data_views_data_alter';
+    $function = $field->module . '_field_views_data_views_data_alter';
     if (function_exists($function)) {
       $function($data, $field);
     }
@@ -72,8 +72,8 @@ function field_views_field_label($field_name) {
   foreach ($instances as $entity_name => $entity_type) {
     foreach ($entity_type as $bundle) {
       if (isset($bundle[$field_name])) {
-        $label_counter[$bundle[$field_name]['label']] = isset($label_counter[$bundle[$field_name]['label']]) ? ++$label_counter[$bundle[$field_name]->label] : 1;
-        $all_labels[$entity_name][$bundle[$field_name]['label']] = TRUE;
+        $label_counter[$bundle[$field_name]->label] = isset($label_counter[$bundle[$field_name]->label]) ? ++$label_counter[$bundle[$field_name]->label] : 1;
+        $all_labels[$entity_name][$bundle[$field_name]->label] = TRUE;
       }
     }
   }
@@ -93,7 +93,7 @@ function field_views_field_default_views_data($field) {
   $field_types = field_info_field_types();
 
   // Check the field module is available.
-  if (!isset($field_types[$field['type']])) {
+  if (!isset($field_types[$field->type])) {
     return;
   }
 
@@ -110,10 +110,10 @@ function field_views_field_default_views_data($field) {
   $revision_tables = array();
   $groups = array();
 
-  $group_name = count($field['bundles']) > 1 ? t('Field') : NULL;
+  $group_name = count($field->getBundles()) > 1 ? t('Field') : NULL;
 
   // Build the relationships between the field table and the entity tables.
-  foreach ($field['bundles'] as $entity => $bundles) {
+  foreach ($field->getBundles() as $entity => $bundles) {
     $entity_info = entity_get_info($entity);
     $groups[$entity] = $entity_info['label'];
 
@@ -171,25 +171,25 @@ function field_views_field_default_views_data($field) {
   }
 
   $add_fields = array('delta', 'langcode', 'bundle');
-  foreach ($field['columns'] as $column_name => $attributes) {
-    $add_fields[] = _field_sql_storage_columnname($field['field_name'], $column_name);
+  foreach ($field->getSchema('columns') as $column_name => $attributes) {
+    $add_fields[] = _field_sql_storage_columnname($field->id(), $column_name);
   }
 
   // Note: we don't have a label available here, because we are at the field
   // level, not at the instance level. So we just go through all instances
   // and take the one which is used the most frequently.
-  $field_name = $field['field_name'];
+  $field_name = $field->id();
   list($label, $all_labels) = field_views_field_label($field_name);
   foreach ($tables as $type => $table) {
     if ($type == FIELD_LOAD_CURRENT) {
       $group = $group_name;
       $old_column = 'entity_id';
-      $column = $field['field_name'];
+      $column = $field->id();
     }
     else {
       $group = t('@group (historical data)', array('@group' => $group_name));
       $old_column = 'revision_id';
-      $column = $field['field_name'] . '-' . $old_column;
+      $column = $field->id() . '-' . $old_column;
     }
 
     $data[$table][$column] = array(
@@ -237,12 +237,12 @@ function field_views_field_default_views_data($field) {
       $data[$table][$column]['help'] .= ' ' . t('Also known as: !also.', array('!also' => implode(', ', $also_known)));
     }
 
-    $keys = array_keys($field['columns']);
+    $keys = array_keys($field->getSchema('columns'));
     $real_field = reset($keys);
     $data[$table][$column]['field'] = array(
       'table' => $table,
       'id' => 'field',
-      'field_name' => $field['field_name'],
+      'field_name' => $field->id(),
       // Provide a real field for group by.
       'real field' => $column . '_' . $real_field,
       'additional fields' => $add_fields,
@@ -253,7 +253,7 @@ function field_views_field_default_views_data($field) {
     );
   }
 
-  foreach ($field['columns'] as $column => $attributes) {
+  foreach ($field->getSchema('columns') as $column => $attributes) {
     $allow_sort = TRUE;
 
     // Identify likely filters and arguments for each column based on field type.
@@ -280,12 +280,12 @@ function field_views_field_default_views_data($field) {
         break;
     }
 
-    if (count($field['columns']) == 1 || $column == 'value') {
-      $title = t('@label (!name)', array('@label' => $label, '!name' => $field['field_name']));
+    if (count($field->getSchema('columns')) == 1 || $column == 'value') {
+      $title = t('@label (!name)', array('@label' => $label, '!name' => $field->id()));
       $title_short = $label;
     }
     else {
-      $title = t('@label (!name:!column)', array('@label' => $label, '!name' => $field['field_name'], '!column' => $column));
+      $title = t('@label (!name:!column)', array('@label' => $label, '!name' => $field->id(), '!column' => $column));
       $title_short = t('@label:!column', array('@label' => $label, '!column' => $column));
     }
 
@@ -296,10 +296,11 @@ function field_views_field_default_views_data($field) {
       else {
         $group = t('@group (historical data)', array('@group' => $group_name));
       }
-      $column_real_name = $field['storage_details']['sql'][$type][$table][$column];
+      $storage_details = $field->getStorageDetails();
+      $column_real_name = $storage_details['sql'][$type][$table][$column];
 
       // Load all the fields from the table by default.
-      $additional_fields = array_values($field['storage_details']['sql'][$type][$table]);
+      $additional_fields = array_values($storage_details['sql'][$type][$table]);
 
       $data[$table][$column_real_name] = array(
         'group' => $group,
@@ -315,11 +316,11 @@ function field_views_field_default_views_data($field) {
       foreach ($all_labels as $entity_name => $labels) {
         foreach ($labels as $label_name => $true) {
           if ($group_name != $groups[$entity_name] || $label != $label_name) {
-            if (count($field['columns']) == 1 || $column == 'value') {
-              $alias_title = t('@label (!name)', array('@label' => $label_name, '!name' => $field['field_name']));
+            if (count($field->getSchema('columns')) == 1 || $column == 'value') {
+              $alias_title = t('@label (!name)', array('@label' => $label_name, '!name' => $field->id()));
             }
             else {
-              $alias_title = t('@label (!name:!column)', array('@label' => $label_name, '!name' => $field['field_name'], '!column' => $column));
+              $alias_title = t('@label (!name:!column)', array('@label' => $label_name, '!name' => $field->id(), '!column' => $column));
             }
             $aliases[] = array(
               'group' => $groups[$entity_name],
@@ -340,7 +341,7 @@ function field_views_field_default_views_data($field) {
         'table' => $table,
         'id' => $argument,
         'additional fields' => $additional_fields,
-        'field_name' => $field['field_name'],
+        'field_name' => $field->id(),
         'empty field name' => t('- No value -'),
       );
       $data[$table][$column_real_name]['filter'] = array(
@@ -348,7 +349,7 @@ function field_views_field_default_views_data($field) {
         'table' => $table,
         'id' => $filter,
         'additional fields' => $additional_fields,
-        'field_name' => $field['field_name'],
+        'field_name' => $field->id(),
         'allow empty' => TRUE,
       );
       if (!empty($allow_sort)) {
@@ -357,13 +358,13 @@ function field_views_field_default_views_data($field) {
           'table' => $table,
           'id' => $sort,
           'additional fields' => $additional_fields,
-          'field_name' => $field['field_name'],
+          'field_name' => $field->id(),
         );
       }
 
       // Expose additional delta column for multiple value fields.
-      if ($field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED) {
-        $title_delta = t('@label (!name:delta)', array('@label' => $label, '!name' => $field['field_name']));
+      if ($field->cardinality > 1 || $field->cardinality == FIELD_CARDINALITY_UNLIMITED) {
+        $title_delta = t('@label (!name:delta)', array('@label' => $label, '!name' => $field->id()));
         $title_short_delta = t('@label:delta', array('@label' => $label));
 
         $data[$table]['delta'] = array(
@@ -381,14 +382,14 @@ function field_views_field_default_views_data($field) {
           'id' => 'numeric',
           'additional fields' => $additional_fields,
           'empty field name' => t('- No value -'),
-          'field_name' => $field['field_name'],
+          'field_name' => $field->id(),
         );
         $data[$table]['delta']['filter'] = array(
           'field' => 'delta',
           'table' => $table,
           'id' => 'numeric',
           'additional fields' => $additional_fields,
-          'field_name' => $field['field_name'],
+          'field_name' => $field->id(),
           'allow empty' => TRUE,
         );
         $data[$table]['delta']['sort'] = array(
@@ -396,13 +397,13 @@ function field_views_field_default_views_data($field) {
           'table' => $table,
           'id' => 'standard',
           'additional fields' => $additional_fields,
-          'field_name' => $field['field_name'],
+          'field_name' => $field->id(),
         );
       }
 
       // Expose additional language column for translatable fields.
-      if (!empty($field['translatable'])) {
-        $title_language = t('@label (!name:language)', array('@label' => $label, '!name' => $field['field_name']));
+      if (!empty($field->translatable)) {
+        $title_language = t('@label (!name:language)', array('@label' => $label, '!name' => $field->id()));
         $title_short_language = t('@label:language', array('@label' => $label));
 
         $data[$table]['language'] = array(
@@ -420,14 +421,14 @@ function field_views_field_default_views_data($field) {
           'id' => 'language',
           'additional fields' => $additional_fields,
           'empty field name' => t('<No value>'),
-          'field_name' => $field['field_name'],
+          'field_name' => $field->id(),
         );
         $data[$table]['language']['filter'] = array(
           'field' => 'language',
           'table' => $table,
           'id' => 'language',
           'additional fields' => $additional_fields,
-          'field_name' => $field['field_name'],
+          'field_name' => $field->id(),
           'allow empty' => TRUE,
         );
         $data[$table]['language']['sort'] = array(
@@ -435,7 +436,7 @@ function field_views_field_default_views_data($field) {
           'table' => $table,
           'id' => 'standard',
           'additional fields' => $additional_fields,
-          'field_name' => $field['field_name'],
+          'field_name' => $field->id(),
         );
       }
     }
@@ -455,7 +456,7 @@ function list_field_views_data($field) {
         $data[$table_name][$field_name]['filter']['id'] = 'field_list';
       }
       if (isset($field_data['argument']) && $field_name != 'delta') {
-        if ($field['type'] == 'list_text') {
+        if ($field->type == 'list_text') {
           $data[$table_name][$field_name]['argument']['id'] = 'field_list_string';
         }
         else {
diff --git a/core/modules/field/lib/Drupal/field/FieldInfo.php b/core/modules/field/lib/Drupal/field/FieldInfo.php
index 6d95788..f4fe7a9 100644
--- a/core/modules/field/lib/Drupal/field/FieldInfo.php
+++ b/core/modules/field/lib/Drupal/field/FieldInfo.php
@@ -223,7 +223,7 @@ public function getFields() {
     else {
       // Collect and prepare fields.
       foreach (field_read_fields(array(), array('include_deleted' => TRUE)) as $field) {
-        $this->fieldsById[$field['uuid']] = $this->prepareField($field);
+        $this->fieldsById[$field->uuid] = $this->prepareField($field);
       }
 
       // Store in persistent cache.
@@ -232,8 +232,8 @@ public function getFields() {
 
     // Fill the name/ID map.
     foreach ($this->fieldsById as $field) {
-      if (!$field['deleted']) {
-        $this->fieldIdsByName[$field['id']] = $field['uuid'];
+      if (!$field->deleted) {
+        $this->fieldIdsByName[$field->id()] = $field->uuid;
       }
     }
 
@@ -269,9 +269,9 @@ public function getInstances($entity_type = NULL) {
         $this->getFields();
 
         foreach (field_read_instances() as $instance) {
-          $field = $this->getField($instance['field_name']);
-          $instance = $this->prepareInstance($instance, $field['type']);
-          $this->bundleInstances[$instance['entity_type']][$instance['bundle']][$instance['field_name']] = $instance;
+          $field = $this->getField($instance->getFieldName());
+          $instance = $this->prepareInstance($instance, $field->type);
+          $this->bundleInstances[$instance->entity_type][$instance->bundle][$instance->getFieldName()] = $instance;
         }
 
         // Store in persistent cache.
@@ -317,8 +317,8 @@ public function getField($field_name) {
       $field = $this->prepareField($field);
 
       // Save in the "static" cache.
-      $this->fieldsById[$field['uuid']] = $field;
-      $this->fieldIdsByName[$field['field_name']] = $field['uuid'];
+      $this->fieldsById[$field->uuid] = $field;
+      $this->fieldIdsByName[$field->id()] = $field->uuid;
 
       return $field;
     }
@@ -356,9 +356,9 @@ public function getFieldById($field_id) {
       $field = $this->prepareField($field);
 
       // Store in the static cache.
-      $this->fieldsById[$field['uuid']] = $field;
-      if (!$field['deleted']) {
-        $this->fieldIdsByName[$field['field_name']] = $field['uuid'];
+      $this->fieldsById[$field->uuid] = $field;
+      if (!$field->deleted) {
+        $this->fieldIdsByName[$field->id()] = $field->uuid;
       }
 
       return $field;
@@ -397,10 +397,10 @@ public function getBundleInstances($entity_type, $bundle) {
 
       // Extract the field definitions and save them in the "static" cache.
       foreach ($info['fields'] as $field) {
-        if (!isset($this->fieldsById[$field['uuid']])) {
-          $this->fieldsById[$field['uuid']] = $field;
-          if (!$field['deleted']) {
-            $this->fieldIdsByName[$field['field_name']] = $field['uuid'];
+        if (!isset($this->fieldsById[$field->uuid])) {
+          $this->fieldsById[$field->uuid] = $field;
+          if (!$field->deleted) {
+            $this->fieldIdsByName[$field->id()] = $field->uuid;
           }
         }
       }
@@ -440,17 +440,17 @@ public function getBundleInstances($entity_type, $bundle) {
         $loaded_instances = entity_load_multiple('field_instance', array_values($config_ids));
 
         foreach ($loaded_instances as $instance) {
-          $field = $loaded_fields[$instance['field_name']];
+          $field = $loaded_fields[$instance->getFieldName()];
 
-          $instance = $this->prepareInstance($instance, $field['type']);
-          $instances[$field['field_name']] = $instance;
+          $instance = $this->prepareInstance($instance, $field->type);
+          $instances[$field->id()] = $instance;
 
           // If the field is not in our global "static" list yet, add it.
-          if (!isset($this->fieldsById[$field['uuid']])) {
+          if (!isset($this->fieldsById[$field->uuid])) {
             $field = $this->prepareField($field);
 
-            $this->fieldsById[$field['uuid']] = $field;
-            $this->fieldIdsByName[$field['field_name']] = $field['uuid'];
+            $this->fieldsById[$field->uuid] = $field;
+            $this->fieldIdsByName[$field->id()] = $field->uuid;
           }
         }
       }
@@ -473,7 +473,7 @@ public function getBundleInstances($entity_type, $bundle) {
       'fields' => array()
     );
     foreach ($instances as $instance) {
-      $cache['fields'][] = $this->fieldsById[$instance['field_id']];
+      $cache['fields'][] = $this->fieldsById[$instance->field_uuid];
     }
     $this->cacheBackend->set("field_info:bundle:$entity_type:$bundle", $cache, CacheBackendInterface::CACHE_PERMANENT, array('field_info' => TRUE));
 
@@ -532,8 +532,8 @@ public function getBundleExtraFields($entity_type, $bundle) {
    */
   public function prepareField($field) {
     // Make sure all expected field settings are present.
-    $field['settings'] += field_info_field_settings($field['type']);
-    $field['storage']['settings'] += field_info_storage_settings($field['storage']['type']);
+    $field->settings += field_info_field_settings($field->type);
+    $field->storage['settings'] += field_info_storage_settings($field->storage['type']);
 
     return $field;
   }
@@ -551,11 +551,11 @@ public function prepareField($field) {
    */
   public function prepareInstance($instance, $field_type) {
     // Make sure all expected instance settings are present.
-    $instance['settings'] += field_info_instance_settings($field_type);
+    $instance->settings += field_info_instance_settings($field_type);
 
     // Set a default value for the instance.
-    if (field_behaviors_widget('default value', $instance) == FIELD_BEHAVIOR_DEFAULT && !isset($instance['default_value'])) {
-      $instance['default_value'] = NULL;
+    if (field_behaviors_widget('default value', $instance) == FIELD_BEHAVIOR_DEFAULT && !isset($instance->default_value)) {
+      $instance->default_value = NULL;
     }
 
     return $instance;
diff --git a/core/modules/field/lib/Drupal/field/FieldInstanceInterface.php b/core/modules/field/lib/Drupal/field/FieldInstanceInterface.php
index d2a0b85..16d0aa2 100644
--- a/core/modules/field/lib/Drupal/field/FieldInstanceInterface.php
+++ b/core/modules/field/lib/Drupal/field/FieldInstanceInterface.php
@@ -13,7 +13,7 @@
 /**
  * Provides an interface defining a field instance entity.
  */
-interface FieldInstanceInterface extends ConfigEntityInterface, FieldDefinitionInterface, \ArrayAccess, \Serializable {
+interface FieldInstanceInterface extends ConfigEntityInterface, FieldDefinitionInterface, \Serializable {
 
   /**
    * Returns the field entity for this instance.
@@ -24,6 +24,22 @@
   public function getField();
 
   /**
+   * Returns the field id for this instance.
+   *
+   * @return $field_id
+   *   The field id.
+   */
+  public function getFieldName();
+
+  /**
+   * Returns the field type from the field for this instance.
+   *
+   * @return $type
+   *   The field type.
+   */
+  public function getFieldType();
+
+  /**
    * Allows a bundle to be renamed.
    *
    * Renaming a bundle on the instance is allowed when an entity's bundle
diff --git a/core/modules/field/lib/Drupal/field/FieldInterface.php b/core/modules/field/lib/Drupal/field/FieldInterface.php
index 83b3de7..24b51c3 100644
--- a/core/modules/field/lib/Drupal/field/FieldInterface.php
+++ b/core/modules/field/lib/Drupal/field/FieldInterface.php
@@ -13,11 +13,14 @@
 /**
  * Provides an interface defining a field entity.
  */
-interface FieldInterface extends ConfigEntityInterface, FieldDefinitionInterface, \ArrayAccess, \Serializable {
+interface FieldInterface extends ConfigEntityInterface, FieldDefinitionInterface, \Serializable {
 
   /**
    * Returns the field schema.
    *
+   * @param string $key
+   *   (optional) A key corresponding to one of the keys in the schema array.
+   *
    * @return array
    *   The field schema, as an array of key/value pairs in the format returned
    *   by hook_field_schema():
@@ -31,7 +34,7 @@
    *     however, that depending on the storage backend specified for the field,
    *     the field data is not necessarily stored in SQL.
    */
-  public function getSchema();
+  public function getSchema($key = '');
 
   /**
    * Returns information about how the storage backend stores the field data.
@@ -64,10 +67,13 @@ public function getStorageDetails();
   /**
    * Returns the list of bundles where the field has instances.
    *
+   * @param string $entity_type
+   *   (optional) The name of the entity type to look for.
+   *
    * @return array
    *   An array keyed by entity type names, whose values are arrays of bundle
    *   names.
    */
-  public function getBundles();
+  public function getBundles($entity_type = '');
 
 }
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/Field.php b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/Field.php
index a8eb4b2..1d0eb20 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/Field.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/Field.php
@@ -492,7 +492,7 @@ public function delete() {
   /**
    * {@inheritdoc}
    */
-  public function getSchema() {
+  public function getSchema($key = '') {
     if (!isset($this->schema)) {
       $module_handler = \Drupal::moduleHandler();
 
@@ -516,6 +516,10 @@ public function getSchema() {
       $this->schema = $schema;
     }
 
+    if (!empty($key)) {
+      return $this->schema[$key];
+    }
+
     return $this->schema;
   }
 
@@ -541,10 +545,15 @@ public function getStorageDetails() {
   /**
    * {@inheritdoc}
    */
-  public function getBundles() {
+  public function getBundles($entity_type = '') {
     if (empty($this->deleted)) {
       $map = field_info_field_map();
-      if (isset($map[$this->id]['bundles'])) {
+      if (!empty($entity_type)) {
+        if (isset($map[$this->id]['bundles'][$entity_type])) {
+          return $map[$this->id]['bundles'][$entity_type];
+        }
+      }
+      elseif (isset($map[$this->id]['bundles'])) {
         return $map[$this->id]['bundles'];
       }
     }
@@ -645,62 +654,6 @@ public function isFieldRequired() {
   /**
    * {@inheritdoc}
    */
-  public function offsetExists($offset) {
-    return isset($this->{$offset}) || in_array($offset, array('columns', 'foreign keys', 'bundles', 'storage_details'));
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function &offsetGet($offset) {
-    switch ($offset) {
-      case 'id':
-        return $this->uuid;
-
-      case 'field_name':
-        return $this->id;
-
-      case 'columns':
-        $this->getSchema();
-        return $this->schema['columns'];
-
-      case 'foreign keys':
-        $this->getSchema();
-        return $this->schema['foreign keys'];
-
-      case 'bundles':
-        $bundles = $this->getBundles();
-        return $bundles;
-
-      case 'storage_details':
-        $this->getStorageDetails();
-        return $this->storageDetails;
-    }
-
-    return $this->{$offset};
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function offsetSet($offset, $value) {
-    if (!in_array($offset, array('columns', 'foreign keys', 'bundles', 'storage_details'))) {
-      $this->{$offset} = $value;
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function offsetUnset($offset) {
-    if (!in_array($offset, array('columns', 'foreign keys', 'bundles', 'storage_details'))) {
-      unset($this->{$offset});
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function serialize() {
     // Only store the definition, not external objects or derived data.
     return serialize($this->getExportProperties());
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php
index 2856acf..db4748b 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php
@@ -571,6 +571,7 @@ public function isFieldRequired() {
     return $this->required;
   }
 
+
   /**
    * {@inheritdoc}
    */
@@ -581,46 +582,6 @@ public function allowBundleRename() {
   /**
    * {@inheritdoc}
    */
-  public function offsetExists($offset) {
-    return (isset($this->{$offset}) || $offset == 'field_id' || $offset == 'field_name');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function &offsetGet($offset) {
-    if ($offset == 'field_id') {
-      return $this->field_uuid;
-    }
-    if ($offset == 'field_name') {
-      return $this->field->id;
-    }
-    return $this->{$offset};
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function offsetSet($offset, $value) {
-    if ($offset == 'field_id') {
-      $offset = 'field_uuid';
-    }
-    $this->{$offset} = $value;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function offsetUnset($offset) {
-    if ($offset == 'field_id') {
-      $offset = 'field_uuid';
-    }
-    unset($this->{$offset});
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function serialize() {
     // Only store the definition, not external objects or derived data.
     return serialize($this->getExportProperties());
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php
index 5cf902b..777d6a1 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php
@@ -46,7 +46,6 @@
    */
   public function __construct($plugin_id, array $plugin_definition, FieldDefinitionInterface $field_definition, array $settings) {
     parent::__construct(array(), $plugin_id, $plugin_definition);
-
     $this->fieldDefinition = $field_definition;
     $this->settings = $settings;
   }
diff --git a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php
index 1342ec5..9d393da 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php
@@ -299,7 +299,7 @@ protected function defineOptions() {
 
     // defineOptions runs before init/construct, so no $this->field_info
     $field = field_info_field($this->definition['field_name']);
-    $field_type = field_info_field_types($field['type']);
+    $field_type = field_info_field_types($field->type);
     $column_names = array_keys($field['columns']);
     $default_column = '';
     // Try to determine a sensible default.
diff --git a/core/modules/field/lib/Drupal/field/Tests/BulkDeleteTest.php b/core/modules/field/lib/Drupal/field/Tests/BulkDeleteTest.php
index d27bd7d..986599f 100644
--- a/core/modules/field/lib/Drupal/field/Tests/BulkDeleteTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/BulkDeleteTest.php
@@ -116,7 +116,7 @@ function setUp() {
     foreach ($this->bundles as $bundle) {
       foreach ($this->fields as $field) {
         $instance = array(
-          'field_name' => $field['field_name'],
+          'field_name' => $field->id(),
           'entity_type' => $this->entity_type,
           'bundle' => $bundle,
         );
@@ -126,7 +126,7 @@ function setUp() {
       for ($i = 0; $i < 10; $i++) {
         $entity = field_test_create_entity($id, $id, $bundle);
         foreach ($this->fields as $field) {
-          $entity->{$field['field_name']}[Language::LANGCODE_NOT_SPECIFIED] = $this->_generateTestFieldValues($field['cardinality']);
+          $entity->{$field->id()}[Language::LANGCODE_NOT_SPECIFIED] = $this->_generateTestFieldValues($field->cardinality);
         }
         $entity->save();
         $id++;
@@ -151,7 +151,7 @@ function setUp() {
   function testDeleteFieldInstance() {
     $bundle = reset($this->bundles);
     $field = reset($this->fields);
-    $field_name = $field['field_name'];
+    $field_name = $field->id();
     $factory = \Drupal::service('entity.query');
 
     // There are 10 entities of this bundle.
@@ -161,13 +161,13 @@ function testDeleteFieldInstance() {
     $this->assertEqual(count($found), 10, 'Correct number of entities found before deleting');
 
     // Delete the instance.
-    $instance = field_info_instance($this->entity_type, $field['field_name'], $bundle);
+    $instance = field_info_instance($this->entity_type, $field->id(), $bundle);
     field_delete_instance($instance);
 
     // The instance still exists, deleted.
-    $instances = field_read_instances(array('field_id' => $field['uuid'], 'deleted' => TRUE), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
+    $instances = field_read_instances(array('field_id' => $field->uuid, 'deleted' => TRUE), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
     $this->assertEqual(count($instances), 1, 'There is one deleted instance');
-    $this->assertEqual($instances[0]['bundle'], $bundle, 'The deleted instance is for the correct bundle');
+    $this->assertEqual($instances[0]->bundle, $bundle, 'The deleted instance is for the correct bundle');
 
     // There are 0 entities of this bundle with non-deleted data.
     $found = $factory->get('test_entity')
@@ -192,10 +192,10 @@ function testDeleteFieldInstance() {
       $ids->entity_id = $entity_id;
       $entities[$entity_id] = _field_create_entity_from_ids($ids);
     }
-    field_attach_load($this->entity_type, $entities, FIELD_LOAD_CURRENT, array('field_id' => $field['uuid'], 'deleted' => TRUE));
+    field_attach_load($this->entity_type, $entities, FIELD_LOAD_CURRENT, array('field_id' => $field->uuid, 'deleted' => TRUE));
     $this->assertEqual(count($found), 10, 'Correct number of entities found after deleting');
     foreach ($entities as $id => $entity) {
-      $this->assertEqual($this->entities[$id]->{$field['field_name']}, $entity->{$field['field_name']}, "Entity $id with deleted data loaded correctly");
+      $this->assertEqual($this->entities[$id]->{$field->id()}, $entity->{$field->id()}, "Entity $id with deleted data loaded correctly");
     }
   }
 
@@ -211,7 +211,7 @@ function testPurgeInstance() {
     $field = reset($this->fields);
 
     // Delete the instance.
-    $instance = field_info_instance($this->entity_type, $field['field_name'], $bundle);
+    $instance = field_info_instance($this->entity_type, $field->id(), $bundle);
     field_delete_instance($instance);
 
     // No field hooks were called.
@@ -226,7 +226,7 @@ function testPurgeInstance() {
       // There are $count deleted entities left.
       $found = \Drupal::entityQuery('test_entity')
         ->condition('fttype', $bundle)
-        ->condition($field['field_name'] . '.deleted', 1)
+        ->condition($field->id() . '.deleted', 1)
         ->execute();
       $this->assertEqual(count($found), $count, 'Correct number of entities found after purging 2');
     }
@@ -238,7 +238,7 @@ function testPurgeInstance() {
     // bundle.
     $actual_hooks = field_test_memorize();
     $hooks = array();
-    $entities = $this->convertToPartialEntities($this->entities_by_bundles[$bundle], $field['field_name']);
+    $entities = $this->convertToPartialEntities($this->entities_by_bundles[$bundle], $field->id());
     foreach (array_chunk($entities, $batch_size, TRUE) as $chunk_entity) {
       $hooks['field_test_field_load'][] = $chunk_entity;
     }
@@ -248,19 +248,19 @@ function testPurgeInstance() {
     $this->checkHooksInvocations($hooks, $actual_hooks);
 
     // The instance still exists, deleted.
-    $instances = field_read_instances(array('field_id' => $field['uuid'], 'deleted' => TRUE), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
+    $instances = field_read_instances(array('field_id' => $field->uuid, 'deleted' => TRUE), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
     $this->assertEqual(count($instances), 1, 'There is one deleted instance');
 
     // Purge the instance.
     field_purge_batch($batch_size);
 
     // The instance is gone.
-    $instances = field_read_instances(array('field_id' => $field['uuid'], 'deleted' => TRUE), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
+    $instances = field_read_instances(array('field_id' => $field->uuid, 'deleted' => TRUE), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
     $this->assertEqual(count($instances), 0, 'The instance is gone');
 
     // The field still exists, not deleted, because it has a second instance.
-    $fields = field_read_fields(array('uuid' => $field['uuid']), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
-    $this->assertTrue(isset($fields[$field['uuid']]), 'The field exists and is not deleted');
+    $fields = field_read_fields(array('uuid' => $field->uuid), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
+    $this->assertTrue(isset($fields[$field->uuid]), 'The field exists and is not deleted');
   }
 
   /**
@@ -275,7 +275,7 @@ function testPurgeField() {
 
     // Delete the first instance.
     $bundle = reset($this->bundles);
-    $instance = field_info_instance($this->entity_type, $field['field_name'], $bundle);
+    $instance = field_info_instance($this->entity_type, $field->id(), $bundle);
     field_delete_instance($instance);
 
     // Assert that hook_field_delete() was not called yet.
@@ -292,7 +292,7 @@ function testPurgeField() {
     // bundle.
     $actual_hooks = field_test_memorize();
     $hooks = array();
-    $entities = $this->convertToPartialEntities($this->entities_by_bundles[$bundle], $field['field_name']);
+    $entities = $this->convertToPartialEntities($this->entities_by_bundles[$bundle], $field->id());
     $hooks['field_test_field_load'][] = $entities;
     $hooks['field_test_field_delete'] = $entities;
     $this->checkHooksInvocations($hooks, $actual_hooks);
@@ -301,12 +301,12 @@ function testPurgeField() {
     field_purge_batch(0);
 
     // The field still exists, not deleted.
-    $fields = field_read_fields(array('uuid' => $field['uuid']), array('include_deleted' => TRUE));
-    $this->assertTrue(isset($fields[$field['uuid']]) && !$fields[$field['uuid']]->deleted, 'The field exists and is not deleted');
+    $fields = field_read_fields(array('uuid' => $field->uuid), array('include_deleted' => TRUE));
+    $this->assertTrue(isset($fields[$field->uuid]) && !$fields[$field->uuid]->deleted, 'The field exists and is not deleted');
 
     // Delete the second instance.
     $bundle = next($this->bundles);
-    $instance = field_info_instance($this->entity_type, $field['field_name'], $bundle);
+    $instance = field_info_instance($this->entity_type, $field->id(), $bundle);
     field_delete_instance($instance);
 
     // Assert that hook_field_delete() was not called yet.
@@ -319,20 +319,20 @@ function testPurgeField() {
     // Check hooks invocations (same as above, for the 2nd bundle).
     $actual_hooks = field_test_memorize();
     $hooks = array();
-    $entities = $this->convertToPartialEntities($this->entities_by_bundles[$bundle], $field['field_name']);
+    $entities = $this->convertToPartialEntities($this->entities_by_bundles[$bundle], $field->id());
     $hooks['field_test_field_load'][] = $entities;
     $hooks['field_test_field_delete'] = $entities;
     $this->checkHooksInvocations($hooks, $actual_hooks);
 
     // The field still exists, deleted.
-    $fields = field_read_fields(array('uuid' => $field['uuid']), array('include_deleted' => TRUE));
-    $this->assertTrue(isset($fields[$field['uuid']]) && $fields[$field['uuid']]->deleted, 'The field exists and is deleted');
+    $fields = field_read_fields(array('uuid' => $field->uuid), array('include_deleted' => TRUE));
+    $this->assertTrue(isset($fields[$field->uuid]) && $fields[$field->uuid]->deleted, 'The field exists and is deleted');
 
     // Purge again to purge the instance and the field.
     field_purge_batch(0);
 
     // The field is gone.
-    $fields = field_read_fields(array('uuid' => $field['uuid']), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
+    $fields = field_read_fields(array('uuid' => $field->uuid), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
     $this->assertEqual(count($fields), 0, 'The field is purged.');
   }
 }
diff --git a/core/modules/field/lib/Drupal/field/Tests/CrudTest.php b/core/modules/field/lib/Drupal/field/Tests/CrudTest.php
index 7960f82..34cabbc 100644
--- a/core/modules/field/lib/Drupal/field/Tests/CrudTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/CrudTest.php
@@ -43,8 +43,8 @@ function testCreateField() {
     field_test_memorize();
     $field = field_create_field($field_definition);
     $mem = field_test_memorize();
-    $this->assertIdentical($mem['field_test_field_create_field'][0][0]['field_name'], $field_definition['field_name'], 'hook_field_create_field() called with correct arguments.');
-    $this->assertIdentical($mem['field_test_field_create_field'][0][0]['type'], $field_definition['type'], 'hook_field_create_field() called with correct arguments.');
+    $this->assertIdentical($mem['field_test_field_create_field'][0][0]->field_name, $field_definition['field_name'], 'hook_field_create_field() called with correct arguments.');
+    $this->assertIdentical($mem['field_test_field_create_field'][0][0]->type, $field_definition['type'], 'hook_field_create_field() called with correct arguments.');
 
     // Read the configuration. Check against raw configuration data rather than
     // the loaded ConfigEntity, to be sure we check that the defaults are
@@ -275,38 +275,38 @@ function testDeleteField() {
 
     // Create two fields (so we can test that only one is deleted).
     $this->field = array('field_name' => 'field_1', 'type' => 'test_field');
-    field_create_field($this->field);
+    $this->field = field_create_field($this->field);
     $this->another_field = array('field_name' => 'field_2', 'type' => 'test_field');
     field_create_field($this->another_field);
 
     // Create instances for each.
     $this->instance_definition = array(
-      'field_name' => $this->field['field_name'],
+      'field_name' => $this->field->id(),
       'entity_type' => 'test_entity',
       'bundle' => 'test_bundle',
     );
     field_create_instance($this->instance_definition);
     $this->another_instance_definition = $this->instance_definition;
-    $this->another_instance_definition['field_name'] = $this->another_field['field_name'];
+    $this->another_instance_definition['field_name'] = $this->another_field->id();
     field_create_instance($this->another_instance_definition);
 
     // Test that the first field is not deleted, and then delete it.
-    $field = field_read_field($this->field['field_name'], array('include_deleted' => TRUE));
-    $this->assertTrue(!empty($field) && empty($field['deleted']), 'A new field is not marked for deletion.');
-    field_delete_field($this->field['field_name']);
+    $field = field_read_field($this->field->id(), array('include_deleted' => TRUE));
+    $this->assertTrue(!empty($field) && empty($field->deleted), 'A new field is not marked for deletion.');
+    field_delete_field($this->field->id());
 
     // Make sure that the field is marked as deleted when it is specifically
     // loaded.
-    $field = field_read_field($this->field['field_name'], array('include_deleted' => TRUE));
-    $this->assertTrue(!empty($field['deleted']), 'A deleted field is marked for deletion.');
+    $field = field_read_field($this->field->id(), array('include_deleted' => TRUE));
+    $this->assertTrue(!empty($field->deleted), 'A deleted field is marked for deletion.');
 
     // Make sure that this field's instance is marked as deleted when it is
     // specifically loaded.
     $instance = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle'], array('include_deleted' => TRUE));
-    $this->assertTrue(!empty($instance['deleted']), 'An instance for a deleted field is marked for deletion.');
+    $this->assertTrue(!empty($instance->deleted), 'An instance for a deleted field is marked for deletion.');
 
     // Try to load the field normally and make sure it does not show up.
-    $field = field_read_field($this->field['field_name']);
+    $field = field_read_field($this->field->id());
     $this->assertTrue(empty($field), 'A deleted field is not loaded by default.');
 
     // Try to load the instance normally and make sure it does not show up.
@@ -314,34 +314,34 @@ function testDeleteField() {
     $this->assertTrue(empty($instance), 'An instance for a deleted field is not loaded by default.');
 
     // Make sure the other field (and its field instance) are not deleted.
-    $another_field = field_read_field($this->another_field['field_name']);
-    $this->assertTrue(!empty($another_field) && empty($another_field['deleted']), 'A non-deleted field is not marked for deletion.');
+    $another_field = field_read_field($this->another_field->id());
+    $this->assertTrue(!empty($another_field) && empty($another_field->deleted), 'A non-deleted field is not marked for deletion.');
     $another_instance = field_read_instance('test_entity', $this->another_instance_definition['field_name'], $this->another_instance_definition['bundle']);
-    $this->assertTrue(!empty($another_instance) && empty($another_instance['deleted']), 'An instance of a non-deleted field is not marked for deletion.');
+    $this->assertTrue(!empty($another_instance) && empty($another_instance->deleted), 'An instance of a non-deleted field is not marked for deletion.');
 
     // Try to create a new field the same name as a deleted field and
     // write data into it.
     field_create_field($this->field);
     field_create_instance($this->instance_definition);
-    $field = field_read_field($this->field['field_name']);
-    $this->assertTrue(!empty($field) && empty($field['deleted']), 'A new field with a previously used name is created.');
+    $field = field_read_field($this->field->id());
+    $this->assertTrue(!empty($field) && empty($field->deleted), 'A new field with a previously used name is created.');
     $instance = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']);
-    $this->assertTrue(!empty($instance) && empty($instance['deleted']), 'A new instance for a previously used field name is created.');
+    $this->assertTrue(!empty($instance) && empty($instance->deleted), 'A new instance for a previously used field name is created.');
 
     // Save an entity with data for the field
-    $entity = field_test_create_entity(0, 0, $instance['bundle']);
+    $entity = field_test_create_entity(0, 0, $instance->bundle);
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
     $values[0]['value'] = mt_rand(1, 127);
-    $entity->{$field['field_name']}[$langcode] = $values;
+    $entity->{$field->id()}[$langcode] = $values;
     $entity_type = 'test_entity';
     field_attach_insert($entity);
 
     // Verify the field is present on load
     $entity = field_test_create_entity(0, 0, $this->instance_definition['bundle']);
     field_attach_load($entity_type, array(0 => $entity));
-    $this->assertIdentical(count($entity->{$field['field_name']}[$langcode]), count($values), "Data in previously deleted field saves and loads correctly");
+    $this->assertIdentical(count($entity->{$field->id()}[$langcode]), count($values), "Data in previously deleted field saves and loads correctly");
     foreach ($values as $delta => $value) {
-      $this->assertEqual($entity->{$field['field_name']}[$langcode][$delta]['value'], $values[$delta]['value'], "Data in previously deleted field saves and loads correctly");
+      $this->assertEqual($entity->{$field->id()}[$langcode][$delta]['value'], $values[$delta]['value'], "Data in previously deleted field saves and loads correctly");
     }
   }
 
@@ -381,7 +381,7 @@ function testUpdateField() {
     do {
       // We need a unique ID for our entity. $cardinality will do.
       $id = $cardinality;
-      $entity = field_test_create_entity($id, $id, $instance['bundle']);
+      $entity = field_test_create_entity($id, $id, $instance->bundle);
       // Fill in the entity with more values than $cardinality.
       for ($i = 0; $i < 20; $i++) {
         $entity->field_update[Language::LANGCODE_NOT_SPECIFIED][$i]['value'] = $i;
@@ -389,15 +389,15 @@ function testUpdateField() {
       // Save the entity.
       field_attach_insert($entity);
       // Load back and assert there are $cardinality number of values.
-      $entity = field_test_create_entity($id, $id, $instance['bundle']);
+      $entity = field_test_create_entity($id, $id, $instance->bundle);
       field_attach_load('test_entity', array($id => $entity));
-      $this->assertEqual(count($entity->field_update[Language::LANGCODE_NOT_SPECIFIED]), $field['cardinality'], 'Cardinality is kept');
+      $this->assertEqual(count($entity->field_update[Language::LANGCODE_NOT_SPECIFIED]), $field->cardinality, 'Cardinality is kept');
       // Now check the values themselves.
       for ($delta = 0; $delta < $cardinality; $delta++) {
         $this->assertEqual($entity->field_update[Language::LANGCODE_NOT_SPECIFIED][$delta]['value'], $delta, 'Value is kept');
       }
       // Increase $cardinality and set the field cardinality to the new value.
-      $field['cardinality'] = ++$cardinality;
+      $field->cardinality = ++$cardinality;
       field_update_field($field);
     } while ($cardinality < 6);
   }
@@ -408,7 +408,7 @@ function testUpdateField() {
   function testUpdateFieldForbid() {
     $field = array('field_name' => 'forbidden', 'type' => 'test_field', 'settings' => array('changeable' => 0, 'unchangeable' => 0));
     $field = field_create_field($field);
-    $field['settings']['changeable']++;
+    $field->settings['changeable']++;
     try {
       field_update_field($field);
       $this->pass(t("A changeable setting can be updated."));
@@ -416,7 +416,7 @@ function testUpdateFieldForbid() {
     catch (FieldException $e) {
       $this->fail(t("An unchangeable setting cannot be updated."));
     }
-    $field['settings']['unchangeable']++;
+    $field->settings['unchangeable']++;
     try {
       field_update_field($field);
       $this->fail(t("An unchangeable setting can be updated."));
diff --git a/core/modules/field/lib/Drupal/field/Tests/DisplayApiTest.php b/core/modules/field/lib/Drupal/field/Tests/DisplayApiTest.php
index 9ca988e..f48a69a 100644
--- a/core/modules/field/lib/Drupal/field/Tests/DisplayApiTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/DisplayApiTest.php
@@ -57,11 +57,11 @@ function setUp() {
     field_create_field($this->field);
     field_create_instance($this->instance);
     // Create a display for the default view mode.
-    entity_get_display($this->instance['entity_type'], $this->instance['bundle'], 'default')
+    entity_get_display($this->instance->entity_type, $this->instance->bundle, 'default')
       ->setComponent($this->field_name, $this->display_options['default'])
       ->save();
     // Create a display for the teaser view mode.
-    entity_get_display($this->instance['entity_type'], $this->instance['bundle'], 'teaser')
+    entity_get_display($this->instance->entity_type, $this->instance->bundle, 'teaser')
       ->setComponent($this->field_name, $this->display_options['teaser'])
       ->save();
 
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php
index b63d48d..825f010 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php
@@ -41,9 +41,9 @@ function setUp() {
       'field_name' => 'test_view_field',
       'type' => 'text',
     );
-    field_create_field($this->field);
+    $this->field = field_create_field($this->field);
     $this->instance = array(
-      'field_name' => $this->field['field_name'],
+      'field_name' => $this->field->id(),
       'entity_type' => 'node',
       'bundle' => $this->content_type,
     );
@@ -52,7 +52,7 @@ function setUp() {
     // Assign display properties for the 'default' and 'teaser' view modes.
     foreach (array('default', 'teaser') as $view_mode) {
       entity_get_display('node', $this->content_type, $view_mode)
-        ->setComponent($this->field['field_name'])
+        ->setComponent($this->field->id())
         ->save();
     }
 
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php
index d16b25a..66a49da 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php
@@ -39,7 +39,7 @@ function testFieldAttachView() {
     $options = array('field_name' => $this->field_name_2);
 
     // Populate values to be displayed.
-    $values = $this->_generateTestFieldValues($this->field['cardinality']);
+    $values = $this->_generateTestFieldValues($this->field->cardinality);
     $entity_init->{$this->field_name}[$langcode] = $values;
     $values_2 = $this->_generateTestFieldValues($this->field_2['cardinality']);
     $entity_init->{$this->field_name_2}[$langcode] = $values_2;
@@ -57,7 +57,7 @@ function testFieldAttachView() {
         'test_formatter_setting' => $formatter_setting,
       ),
     );
-    $display->setComponent($this->field['field_name'], $display_options);
+    $display->setComponent($this->field->id(), $display_options);
 
     $formatter_setting_2 = $this->randomName();
     $display_options_2 = array(
@@ -74,7 +74,7 @@ function testFieldAttachView() {
     $entity->content = field_attach_view($entity, $display);
     $output = drupal_render($entity->content);
     $this->content = $output;
-    $this->assertRaw($this->instance['label'], "First field's label is displayed.");
+    $this->assertRaw($this->instance->label(), "First field's label is displayed.");
     foreach ($values as $delta => $value) {
       $this->content = $output;
       $this->assertRaw("$formatter_setting|{$value['value']}", "Value $delta is displayed, formatter settings are applied.");
@@ -89,7 +89,7 @@ function testFieldAttachView() {
     $entity->content = field_attach_view($entity, $display, $langcode, $options);
     $output = drupal_render($entity->content);
     $this->content = $output;
-    $this->assertNoRaw($this->instance['label'], "First field's label is not displayed.");
+    $this->assertNoRaw($this->instance->label(), "First field's label is not displayed.");
     foreach ($values as $delta => $value) {
       $this->content = $output;
       $this->assertNoRaw("$formatter_setting|{$value['value']}", "Value $delta is displayed, formatter settings are applied.");
@@ -103,21 +103,21 @@ function testFieldAttachView() {
     // Label hidden.
     $entity = clone($entity_init);
     $display_options['label'] = 'hidden';
-    $display->setComponent($this->field['field_name'], $display_options);
+    $display->setComponent($this->field->id(), $display_options);
     field_attach_prepare_view($entity_type, array($entity->ftid => $entity), $displays);
     $entity->content = field_attach_view($entity, $display);
     $output = drupal_render($entity->content);
     $this->content = $output;
-    $this->assertNoRaw($this->instance['label'], "Hidden label: label is not displayed.");
+    $this->assertNoRaw($this->instance->label(), "Hidden label: label is not displayed.");
 
     // Field hidden.
     $entity = clone($entity_init);
-    $display->removeComponent($this->field['field_name']);
+    $display->removeComponent($this->field->id());
     field_attach_prepare_view($entity_type, array($entity->ftid => $entity), $displays);
     $entity->content = field_attach_view($entity, $display);
     $output = drupal_render($entity->content);
     $this->content = $output;
-    $this->assertNoRaw($this->instance['label'], "Hidden field: label is not displayed.");
+    $this->assertNoRaw($this->instance->label(), "Hidden field: label is not displayed.");
     foreach ($values as $delta => $value) {
       $this->assertNoRaw("$formatter_setting|{$value['value']}", "Hidden field: value $delta is not displayed.");
     }
@@ -125,7 +125,7 @@ function testFieldAttachView() {
     // Multiple formatter.
     $entity = clone($entity_init);
     $formatter_setting = $this->randomName();
-    $display->setComponent($this->field['field_name'], array(
+    $display->setComponent($this->field->id(), array(
       'label' => 'above',
       'type' => 'field_test_multiple',
       'settings' => array(
@@ -145,7 +145,7 @@ function testFieldAttachView() {
     // Test a formatter that uses hook_field_formatter_prepare_view().
     $entity = clone($entity_init);
     $formatter_setting = $this->randomName();
-    $display->setComponent($this->field['field_name'], array(
+    $display->setComponent($this->field->id(), array(
       'label' => 'above',
       'type' => 'field_test_with_prepare_view',
       'settings' => array(
@@ -186,7 +186,7 @@ function testFieldAttachPrepareViewMultiple() {
 
     // Set the instance to be hidden.
     $display = entity_get_display('test_entity', 'test_bundle', 'full')
-      ->removeComponent($this->field['field_name']);
+      ->removeComponent($this->field->id());
 
     // Set up a second instance on another bundle, with a formatter that uses
     // hook_field_formatter_prepare_view().
@@ -197,7 +197,7 @@ function testFieldAttachPrepareViewMultiple() {
     field_create_instance($this->instance2);
 
     $display_2 = entity_get_display('test_entity', 'test_bundle_2', 'full')
-      ->setComponent($this->field['field_name'], array(
+      ->setComponent($this->field->id(), array(
         'type' => 'field_test_with_prepare_view',
         'settings' => array(
           'test_formatter_setting_additional' => $formatter_setting,
@@ -208,11 +208,11 @@ function testFieldAttachPrepareViewMultiple() {
 
     // Create one entity in each bundle.
     $entity1_init = field_test_create_entity(1, 1, 'test_bundle');
-    $values1 = $this->_generateTestFieldValues($this->field['cardinality']);
+    $values1 = $this->_generateTestFieldValues($this->field->cardinality);
     $entity1_init->{$this->field_name}[$langcode] = $values1;
 
     $entity2_init = field_test_create_entity(2, 2, 'test_bundle_2');
-    $values2 = $this->_generateTestFieldValues($this->field['cardinality']);
+    $values2 = $this->_generateTestFieldValues($this->field->cardinality);
     $entity2_init->{$this->field_name}[$langcode] = $values2;
 
     // Run prepare_view, and check that the entities come out as expected.
@@ -237,9 +237,9 @@ function testFieldAttachPrepareViewMultiple() {
    */
   function testFieldAttachCache() {
     // Initialize random values and a test entity.
-    $entity_init = field_test_create_entity(1, 1, $this->instance['bundle']);
+    $entity_init = field_test_create_entity(1, 1, $this->instance->bundle);
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
-    $values = $this->_generateTestFieldValues($this->field['cardinality']);
+    $values = $this->_generateTestFieldValues($this->field->cardinality);
 
     // Non-cacheable entity type.
     $entity_type = 'test_entity';
@@ -265,11 +265,11 @@ function testFieldAttachCache() {
     $entity_init = entity_create($entity_type, array(
       'ftid' => 1,
       'ftvid' => 1,
-      'fttype' => $this->instance['bundle'],
+      'fttype' => $this->instance->bundle,
     ));
     $cid = "field:$entity_type:{$entity_init->ftid}";
     $instance = $this->instance;
-    $instance['entity_type'] = $entity_type;
+    $instance->entity_type = $entity_type;
     field_create_instance($instance);
 
     // Check that no initial cache entry is present.
@@ -294,7 +294,7 @@ function testFieldAttachCache() {
     $this->assertEqual($cache->data[$this->field_name][$langcode], $values, 'Cached: correct cache entry on load');
 
     // Update with different values, and check that the cache entry is wiped.
-    $values = $this->_generateTestFieldValues($this->field['cardinality']);
+    $values = $this->_generateTestFieldValues($this->field->cardinality);
     $entity = clone($entity_init);
     $entity->{$this->field_name}[$langcode] = $values;
     field_attach_update($entity);
@@ -310,9 +310,9 @@ function testFieldAttachCache() {
     $entity_init = entity_create($entity_type, array(
       'ftid' => 1,
       'ftvid' => 2,
-      'fttype' => $this->instance['bundle'],
+      'fttype' => $this->instance->bundle,
     ));
-    $values = $this->_generateTestFieldValues($this->field['cardinality']);
+    $values = $this->_generateTestFieldValues($this->field->cardinality);
     $entity = clone($entity_init);
     $entity->{$this->field_name}[$langcode] = $values;
     field_attach_update($entity);
@@ -340,12 +340,12 @@ function testFieldAttachValidate() {
     $this->createFieldWithInstance('_2');
 
     $entity_type = 'test_entity';
-    $entity = field_test_create_entity(0, 0, $this->instance['bundle']);
+    $entity = field_test_create_entity(0, 0, $this->instance->bundle);
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
 
     // Set up all but one values of the first field to generate errors.
     $values = array();
-    for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
+    for ($delta = 0; $delta < $this->field->cardinality; $delta++) {
       $values[$delta]['value'] = -1;
     }
     // Arrange for item 1 not to generate an error.
@@ -432,18 +432,18 @@ function testFieldAttachForm() {
     $this->createFieldWithInstance('_2');
 
     $entity_type = 'test_entity';
-    $entity = field_test_create_entity(0, 0, $this->instance['bundle']);
+    $entity = field_test_create_entity(0, 0, $this->instance->bundle);
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
 
     // When generating form for all fields.
     $form = array();
     $form_state = form_state_defaults();
-    $form_state['form_display'] = entity_get_form_display($entity_type, $this->instance['bundle'], 'default');
+    $form_state['form_display'] = entity_get_form_display($entity_type, $this->instance->bundle, 'default');
     field_attach_form($entity, $form, $form_state);
 
-    $this->assertEqual($form[$this->field_name][$langcode]['#title'], $this->instance['label'], "First field's form title is {$this->instance['label']}");
-    $this->assertEqual($form[$this->field_name_2][$langcode]['#title'], $this->instance_2['label'], "Second field's form title is {$this->instance_2['label']}");
-    for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
+    $this->assertEqual($form[$this->field_name][$langcode]['#title'], $this->instance->label(), "First field's form title is {$this->instance->label()}");
+    $this->assertEqual($form[$this->field_name_2][$langcode]['#title'], $this->instance_2->label(), "Second field's form title is {$this->instance_2->label()}");
+    for ($delta = 0; $delta < $this->field->cardinality; $delta++) {
       // field_test_widget uses 'textfield'
       $this->assertEqual($form[$this->field_name][$langcode][$delta]['value']['#type'], 'textfield', "First field's form delta $delta widget is textfield");
     }
@@ -456,7 +456,7 @@ function testFieldAttachForm() {
     $options = array('field_name' => $this->field_name_2);
     $form = array();
     $form_state = form_state_defaults();
-    $form_state['form_display'] = entity_get_form_display($entity_type, $this->instance['bundle'], 'default');
+    $form_state['form_display'] = entity_get_form_display($entity_type, $this->instance->bundle, 'default');
     field_attach_form($entity, $form, $form_state, NULL, $options);
 
     $this->assertFalse(isset($form[$this->field_name]), 'The first field does not exist in the form');
@@ -474,24 +474,24 @@ function testFieldAttachExtractFormValues() {
     $this->createFieldWithInstance('_2');
 
     $entity_type = 'test_entity';
-    $entity_init = field_test_create_entity(0, 0, $this->instance['bundle']);
+    $entity_init = field_test_create_entity(0, 0, $this->instance->bundle);
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
 
     // Build the form for all fields.
     $form = array();
     $form_state = form_state_defaults();
-    $form_state['form_display'] = entity_get_form_display($entity_type, $this->instance['bundle'], 'default');
+    $form_state['form_display'] = entity_get_form_display($entity_type, $this->instance->bundle, 'default');
     field_attach_form($entity_init, $form, $form_state);
 
     // Simulate incoming values.
     // First field.
     $values = array();
     $weights = array();
-    for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
+    for ($delta = 0; $delta < $this->field->cardinality; $delta++) {
       $values[$delta]['value'] = mt_rand(1, 127);
       // Assign random weight.
       do {
-        $weight = mt_rand(0, $this->field['cardinality']);
+        $weight = mt_rand(0, $this->field->cardinality);
       } while (in_array($weight, $weights));
       $weights[$delta] = $weight;
       $values[$delta]['_weight'] = $weight;
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php
index 7192067..b16fb79 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php
@@ -38,7 +38,7 @@ public function setUp() {
   function testFieldAttachSaveLoad() {
     // Configure the instance so that we test hook_field_load() (see
     // field_test_field_load() in field_test.module).
-    $this->instance['settings']['test_hook_field_load'] = TRUE;
+    $this->instance->settings['test_hook_field_load'] = TRUE;
     field_update_instance($this->instance);
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
 
@@ -49,9 +49,9 @@ function testFieldAttachSaveLoad() {
 
     // Preparation: create three revisions and store them in $revision array.
     for ($revision_id = 0; $revision_id < 3; $revision_id++) {
-      $revision[$revision_id] = field_test_create_entity(0, $revision_id, $this->instance['bundle']);
+      $revision[$revision_id] = field_test_create_entity(0, $revision_id, $this->instance->bundle);
       // Note: we try to insert one extra value.
-      $values[$revision_id] = $this->_generateTestFieldValues($this->field['cardinality'] + 1);
+      $values[$revision_id] = $this->_generateTestFieldValues($this->field->cardinality + 1);
       $current_revision = $revision_id;
       // If this is the first revision do an insert.
       if (!$revision_id) {
@@ -66,11 +66,11 @@ function testFieldAttachSaveLoad() {
     }
 
     // Confirm current revision loads the correct data.
-    $entity = field_test_create_entity(0, 0, $this->instance['bundle']);
+    $entity = field_test_create_entity(0, 0, $this->instance->bundle);
     field_attach_load($entity_type, array(0 => $entity));
     // Number of values per field loaded equals the field cardinality.
-    $this->assertEqual(count($entity->{$this->field_name}[$langcode]), $this->field['cardinality'], 'Current revision: expected number of values');
-    for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
+    $this->assertEqual(count($entity->{$this->field_name}[$langcode]), $this->field->cardinality, 'Current revision: expected number of values');
+    for ($delta = 0; $delta < $this->field->cardinality; $delta++) {
       // The field value loaded matches the one inserted or updated.
       $this->assertEqual($entity->{$this->field_name}[$langcode][$delta]['value'] , $values[$current_revision][$delta]['value'], format_string('Current revision: expected value %delta was found.', array('%delta' => $delta)));
       // The value added in hook_field_load() is found.
@@ -79,11 +79,11 @@ function testFieldAttachSaveLoad() {
 
     // Confirm each revision loads the correct data.
     foreach (array_keys($revision) as $revision_id) {
-      $entity = field_test_create_entity(0, $revision_id, $this->instance['bundle']);
+      $entity = field_test_create_entity(0, $revision_id, $this->instance->bundle);
       field_attach_load_revision($entity_type, array(0 => $entity));
       // Number of values per field loaded equals the field cardinality.
-      $this->assertEqual(count($entity->{$this->field_name}[$langcode]), $this->field['cardinality'], format_string('Revision %revision_id: expected number of values.', array('%revision_id' => $revision_id)));
-      for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
+      $this->assertEqual(count($entity->{$this->field_name}[$langcode]), $this->field->cardinality, format_string('Revision %revision_id: expected number of values.', array('%revision_id' => $revision_id)));
+      for ($delta = 0; $delta < $this->field->cardinality; $delta++) {
         // The field value loaded matches the one inserted or updated.
         $this->assertEqual($entity->{$this->field_name}[$langcode][$delta]['value'], $values[$revision_id][$delta]['value'], format_string('Revision %revision_id: expected value %delta was found.', array('%revision_id' => $revision_id, '%delta' => $delta)));
         // The value added in hook_field_load() is found.
@@ -119,7 +119,7 @@ function testFieldAttachLoadMultiple() {
       $field_names[$i] = 'field_' . $i;
       $field = array('field_name' => $field_names[$i], 'type' => 'test_field');
       $field = field_create_field($field);
-      $field_ids[$i] = $field['uuid'];
+      $field_ids[$i] = $field->uuid;
       foreach ($field_bundles_map[$i] as $bundle) {
         $instance = array(
           'field_name' => $field_names[$i],
@@ -193,7 +193,7 @@ function testFieldAttachSaveLoadDifferentStorage() {
     foreach ($fields as $field) {
       field_create_field($field);
       $instance = array(
-        'field_name' => $field['field_name'],
+        'field_name' => $field->id(),
         'entity_type' => 'test_entity',
         'bundle' => 'test_bundle',
       );
@@ -206,8 +206,8 @@ function testFieldAttachSaveLoadDifferentStorage() {
     $entity = clone($entity_init);
     $values = array();
     foreach ($fields as $field) {
-      $values[$field['field_name']] = $this->_generateTestFieldValues($this->field['cardinality']);
-      $entity->{$field['field_name']}[$langcode] = $values[$field['field_name']];
+      $values[$field->id()] = $this->_generateTestFieldValues($this->field->cardinality);
+      $entity->{$field->id()}[$langcode] = $values[$field->id()];
     }
     field_attach_insert($entity);
 
@@ -215,7 +215,7 @@ function testFieldAttachSaveLoadDifferentStorage() {
     $entity = clone($entity_init);
     field_attach_load($entity_type, array($entity->ftid => $entity));
     foreach ($fields as $field) {
-      $this->assertEqual($values[$field['field_name']], $entity->{$field['field_name']}[$langcode], format_string('%storage storage: expected values were found.', array('%storage' => $field['storage']['type'])));
+      $this->assertEqual($values[$field->id()], $entity->{$field->id()}[$langcode], format_string('%storage storage: expected values were found.', array('%storage' => $field->storage['type'])));
     }
   }
 
@@ -240,13 +240,14 @@ function testFieldStorageDetailsAlter() {
     );
     field_create_instance($instance);
 
-    $field = field_info_field($instance['field_name']);
-    $instance = field_info_instance($instance['entity_type'], $instance['field_name'], $instance['bundle']);
+    $field = field_info_field($instance->getFieldName());
+    $instance = field_info_instance($instance->entity_type, $instance->getFieldName(), $instance->bundle);
 
     // The storage details are indexed by a storage engine type.
-    $this->assertTrue(array_key_exists('drupal_variables', $field['storage_details']), 'The storage type is Drupal variables.');
+    $this->assertTrue(array_key_exists('drupal_variables', $field->getStorageDetails()), 'The storage type is Drupal variables.');
 
-    $details = $field['storage_details']['drupal_variables'];
+    $storage_details = $field->getStorageDetails();
+    $details = $storage_details['drupal_variables'];
 
     // The field_test storage details are indexed by variable name. The details
     // are altered, so moon and mars are correct for this test.
@@ -255,7 +256,7 @@ function testFieldStorageDetailsAlter() {
 
     // Test current and revision storage details together because the columns
     // are the same.
-    foreach ($field['columns'] as $column_name => $attributes) {
+    foreach ($field->getSchema('columns') as $column_name => $attributes) {
       $this->assertEqual($details[FIELD_LOAD_CURRENT]['moon'][$column_name], $column_name, format_string('Column name %value matches the definition in %bin.', array('%value' => $column_name, '%bin' => 'moon[FIELD_LOAD_CURRENT]')));
       $this->assertEqual($details[FIELD_LOAD_REVISION]['mars'][$column_name], $column_name, format_string('Column name %value matches the definition in %bin.', array('%value' => $column_name, '%bin' => 'mars[FIELD_LOAD_REVISION]')));
     }
@@ -344,7 +345,7 @@ function testFieldAttachSaveMissingData() {
    */
   function testFieldAttachSaveMissingDataDefaultValue() {
     // Add a default value function.
-    $this->instance['default_value_function'] = 'field_test_default_value';
+    $this->instance->default_value_function = 'field_test_default_value';
     field_update_instance($this->instance);
 
     // Verify that fields are populated with default values.
@@ -386,51 +387,51 @@ function testFieldAttachSaveMissingDataDefaultValue() {
   function testFieldAttachDelete() {
     $entity_type = 'test_entity';
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
-    $rev[0] = field_test_create_entity(0, 0, $this->instance['bundle']);
+    $rev[0] = field_test_create_entity(0, 0, $this->instance->bundle);
 
     // Create revision 0
-    $values = $this->_generateTestFieldValues($this->field['cardinality']);
+    $values = $this->_generateTestFieldValues($this->field->cardinality);
     $rev[0]->{$this->field_name}[$langcode] = $values;
     field_attach_insert($rev[0]);
 
     // Create revision 1
-    $rev[1] = field_test_create_entity(0, 1, $this->instance['bundle']);
+    $rev[1] = field_test_create_entity(0, 1, $this->instance->bundle);
     $rev[1]->{$this->field_name}[$langcode] = $values;
     field_attach_update($rev[1]);
 
     // Create revision 2
-    $rev[2] = field_test_create_entity(0, 2, $this->instance['bundle']);
+    $rev[2] = field_test_create_entity(0, 2, $this->instance->bundle);
     $rev[2]->{$this->field_name}[$langcode] = $values;
     field_attach_update($rev[2]);
 
     // Confirm each revision loads
     foreach (array_keys($rev) as $vid) {
-      $read = field_test_create_entity(0, $vid, $this->instance['bundle']);
+      $read = field_test_create_entity(0, $vid, $this->instance->bundle);
       field_attach_load_revision($entity_type, array(0 => $read));
-      $this->assertEqual(count($read->{$this->field_name}[$langcode]), $this->field['cardinality'], "The test entity revision $vid has {$this->field['cardinality']} values.");
+      $this->assertEqual(count($read->{$this->field_name}[$langcode]), $this->field->cardinality, "The test entity revision $vid has {$this->field->cardinality} values.");
     }
 
     // Delete revision 1, confirm the other two still load.
     field_attach_delete_revision($rev[1]);
     foreach (array(0, 2) as $vid) {
-      $read = field_test_create_entity(0, $vid, $this->instance['bundle']);
+      $read = field_test_create_entity(0, $vid, $this->instance->bundle);
       field_attach_load_revision($entity_type, array(0 => $read));
-      $this->assertEqual(count($read->{$this->field_name}[$langcode]), $this->field['cardinality'], "The test entity revision $vid has {$this->field['cardinality']} values.");
+      $this->assertEqual(count($read->{$this->field_name}[$langcode]), $this->field->cardinality, "The test entity revision $vid has {$this->field->cardinality} values.");
     }
 
     // Confirm the current revision still loads
-    $read = field_test_create_entity(0, 2, $this->instance['bundle']);
+    $read = field_test_create_entity(0, 2, $this->instance->bundle);
     field_attach_load($entity_type, array(0 => $read));
-    $this->assertEqual(count($read->{$this->field_name}[$langcode]), $this->field['cardinality'], "The test entity current revision has {$this->field['cardinality']} values.");
+    $this->assertEqual(count($read->{$this->field_name}[$langcode]), $this->field->cardinality, "The test entity current revision has {$this->field->cardinality} values.");
 
     // Delete all field data, confirm nothing loads
     field_attach_delete($rev[2]);
     foreach (array(0, 1, 2) as $vid) {
-      $read = field_test_create_entity(0, $vid, $this->instance['bundle']);
+      $read = field_test_create_entity(0, $vid, $this->instance->bundle);
       field_attach_load_revision($entity_type, array(0 => $read));
       $this->assertIdentical($read->{$this->field_name}, array(), "The test entity revision $vid is deleted.");
     }
-    $read = field_test_create_entity(0, 2, $this->instance['bundle']);
+    $read = field_test_create_entity(0, 2, $this->instance->bundle);
     field_attach_load($entity_type, array(0 => $read));
     $this->assertIdentical($read->{$this->field_name}, array(), 'The test entity current revision is deleted.');
   }
@@ -444,34 +445,34 @@ function testEntityCreateRenameBundle() {
     field_test_create_bundle($new_bundle);
 
     // Add an instance to that bundle.
-    $this->instance['bundle'] = $new_bundle;
+    $this->instance->bundle = $new_bundle;
     field_create_instance($this->instance);
 
     // Save an entity with data in the field.
-    $entity = field_test_create_entity(0, 0, $this->instance['bundle']);
+    $entity = field_test_create_entity(0, 0, $this->instance->bundle);
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
-    $values = $this->_generateTestFieldValues($this->field['cardinality']);
+    $values = $this->_generateTestFieldValues($this->field->cardinality);
     $entity->{$this->field_name}[$langcode] = $values;
     $entity_type = 'test_entity';
     field_attach_insert($entity);
 
     // Verify the field data is present on load.
-    $entity = field_test_create_entity(0, 0, $this->instance['bundle']);
+    $entity = field_test_create_entity(0, 0, $this->instance->bundle);
     field_attach_load($entity_type, array(0 => $entity));
-    $this->assertEqual(count($entity->{$this->field_name}[$langcode]), $this->field['cardinality'], "Data is retrieved for the new bundle");
+    $this->assertEqual(count($entity->{$this->field_name}[$langcode]), $this->field->cardinality, "Data is retrieved for the new bundle");
 
     // Rename the bundle.
     $new_bundle = 'test_bundle_' . drupal_strtolower($this->randomName());
-    field_test_rename_bundle($this->instance['bundle'], $new_bundle);
+    field_test_rename_bundle($this->instance->bundle, $new_bundle);
 
     // Check that the instance definition has been updated.
     $this->instance = field_info_instance($entity_type, $this->field_name, $new_bundle);
-    $this->assertIdentical($this->instance['bundle'], $new_bundle, "Bundle name has been updated in the instance.");
+    $this->assertIdentical($this->instance->bundle, $new_bundle, "Bundle name has been updated in the instance.");
 
     // Verify the field data is present on load.
     $entity = field_test_create_entity(0, 0, $new_bundle);
     field_attach_load($entity_type, array(0 => $entity));
-    $this->assertEqual(count($entity->{$this->field_name}[$langcode]), $this->field['cardinality'], "Bundle name has been updated in the field storage");
+    $this->assertEqual(count($entity->{$this->field_name}[$langcode]), $this->field->cardinality, "Bundle name has been updated in the field storage");
   }
 
   /**
@@ -483,7 +484,7 @@ function testEntityDeleteBundle() {
     field_test_create_bundle($new_bundle);
 
     // Add an instance to that bundle.
-    $this->instance['bundle'] = $new_bundle;
+    $this->instance->bundle = $new_bundle;
     field_create_instance($this->instance);
 
     // Create a second field for the test bundle
@@ -493,7 +494,7 @@ function testEntityDeleteBundle() {
     $instance = array(
       'field_name' => $field_name,
       'entity_type' => 'test_entity',
-      'bundle' => $this->instance['bundle'],
+      'bundle' => $this->instance->bundle,
       'label' => $this->randomName() . '_label',
       'description' => $this->randomName() . '_description',
       'weight' => mt_rand(0, 127),
@@ -501,30 +502,30 @@ function testEntityDeleteBundle() {
     field_create_instance($instance);
 
     // Save an entity with data for both fields
-    $entity = field_test_create_entity(0, 0, $this->instance['bundle']);
+    $entity = field_test_create_entity(0, 0, $this->instance->bundle);
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
-    $values = $this->_generateTestFieldValues($this->field['cardinality']);
+    $values = $this->_generateTestFieldValues($this->field->cardinality);
     $entity->{$this->field_name}[$langcode] = $values;
     $entity->{$field_name}[$langcode] = $this->_generateTestFieldValues(1);
     field_attach_insert($entity);
 
     // Verify the fields are present on load
-    $entity = field_test_create_entity(0, 0, $this->instance['bundle']);
+    $entity = field_test_create_entity(0, 0, $this->instance->bundle);
     field_attach_load('test_entity', array(0 => $entity));
     $this->assertEqual(count($entity->{$this->field_name}[$langcode]), 4, 'First field got loaded');
     $this->assertEqual(count($entity->{$field_name}[$langcode]), 1, 'Second field got loaded');
 
     // Delete the bundle.
-    field_test_delete_bundle($this->instance['bundle']);
+    field_test_delete_bundle($this->instance->bundle);
 
     // Verify no data gets loaded
-    $entity = field_test_create_entity(0, 0, $this->instance['bundle']);
+    $entity = field_test_create_entity(0, 0, $this->instance->bundle);
     field_attach_load('test_entity', array(0 => $entity));
     $this->assertFalse(isset($entity->{$this->field_name}[$langcode]), 'No data for first field');
     $this->assertFalse(isset($entity->{$field_name}[$langcode]), 'No data for second field');
 
     // Verify that the instances are gone
-    $this->assertFalse(field_read_instance('test_entity', $this->field_name, $this->instance['bundle']), "First field is deleted");
-    $this->assertFalse(field_read_instance('test_entity', $field_name, $instance['bundle']), "Second field is deleted");
+    $this->assertFalse(field_read_instance('test_entity', $this->field_name, $this->instance->bundle), "First field is deleted");
+    $this->assertFalse(field_read_instance('test_entity', $field_name, $instance->bundle), "Second field is deleted");
   }
 }
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldImportChangeTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldImportChangeTest.php
index 523687b..09bdd1f 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldImportChangeTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldImportChangeTest.php
@@ -44,7 +44,7 @@ function testImportChange() {
     // Save as files in the the staging directory.
     $instance = $active->read($instance_config_name);
     $new_label = 'Test update import field';
-    $instance['label'] = $new_label;
+    $instance->label = $new_label;
     $staging->write($instance_config_name, $instance);
 
     // Import the content of the staging directory.
@@ -52,7 +52,7 @@ function testImportChange() {
 
     // Check that the updated config was correctly imported.
     $instance = entity_load('field_instance', $instance_id);
-    $this->assertEqual($instance['label'], $new_label, 'Instance label updated');
+    $this->assertEqual($instance->label(), $new_label, 'Instance label updated');
   }
 }
 
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php
index dad0e54..1ab9500 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php
@@ -58,43 +58,43 @@ function testFieldInfo() {
       'field_name' => drupal_strtolower($this->randomName()),
       'type' => 'test_field',
     );
-    field_create_field($field);
+    $field = field_create_field($field);
     $fields = field_info_fields();
     $this->assertEqual(count($fields), count($core_fields) + 1, 'One new field exists');
-    $this->assertEqual($fields[$field['field_name']]['field_name'], $field['field_name'], 'info fields contains field name');
-    $this->assertEqual($fields[$field['field_name']]['type'], $field['type'], 'info fields contains field type');
-    $this->assertEqual($fields[$field['field_name']]['module'], 'field_test', 'info fields contains field module');
+    $this->assertEqual($fields[$field->id()]->id(), $field->id(), 'info fields contains field name');
+    $this->assertEqual($fields[$field->id()]->type, $field->type, 'info fields contains field type');
+    $this->assertEqual($fields[$field->id()]->module, 'field_test', 'info fields contains field module');
     $settings = array('test_field_setting' => 'dummy test string');
     foreach ($settings as $key => $val) {
-      $this->assertEqual($fields[$field['field_name']]['settings'][$key], $val, format_string('Field setting %key has correct default value %value', array('%key' => $key, '%value' => $val)));
+      $this->assertEqual($fields[$field->id()]->settings[$key], $val, format_string('Field setting %key has correct default value %value', array('%key' => $key, '%value' => $val)));
     }
-    $this->assertEqual($fields[$field['field_name']]['cardinality'], 1, 'info fields contains cardinality 1');
-    $this->assertEqual($fields[$field['field_name']]['active'], TRUE, 'info fields contains active 1');
+    $this->assertEqual($fields[$field->id()]->cardinality, 1, 'info fields contains cardinality 1');
+    $this->assertEqual($fields[$field->id()]->active, TRUE, 'info fields contains active 1');
 
     // Create an instance, verify that it shows up
     $instance = array(
-      'field_name' => $field['field_name'],
+      'field_name' => $field->id(),
       'entity_type' => 'test_entity',
       'bundle' => 'test_bundle',
       'label' => $this->randomName(),
       'description' => $this->randomName(),
       'weight' => mt_rand(0, 127),
     );
-    field_create_instance($instance);
+    $instance = field_create_instance($instance);
 
     $info = entity_get_info('test_entity');
-    $instances = field_info_instances('test_entity', $instance['bundle']);
+    $instances = field_info_instances('test_entity', $instance->bundle);
     $this->assertEqual(count($instances), 1, format_string('One instance shows up in info when attached to a bundle on a @label.', array(
       '@label' => $info['label']
     )));
-    $this->assertTrue($instance < $instances[$instance['field_name']], 'Instance appears in info correctly');
+    $this->assertTrue(isset($instances[$instance->getFieldName()]), 'Instance appears in info correctly');
 
     // Test a valid entity type but an invalid bundle.
     $instances = field_info_instances('test_entity', 'invalid_bundle');
     $this->assertIdentical($instances, array(), "field_info_instances('test_entity', 'invalid_bundle') returns an empty array.");
 
     // Test invalid entity type and bundle.
-    $instances = field_info_instances('invalid_entity', $instance['bundle']);
+    $instances = field_info_instances('invalid_entity', $instance->bundle);
     $this->assertIdentical($instances, array(), "field_info_instances('invalid_entity', 'test_bundle') returns an empty array.");
 
     // Test invalid entity type, no bundle provided.
@@ -142,7 +142,7 @@ function testFieldPrepare() {
 
     // Check that all expected settings are in place.
     $field_type = field_info_field_types($field_definition['type']);
-    $this->assertEqual($field['settings'], $field_type['settings'], 'All expected default field settings are present.');
+    $this->assertEqual($field->settings, $field_type['settings'], 'All expected default field settings are present.');
   }
 
   /**
@@ -176,7 +176,7 @@ function testInstancePrepare() {
 
     // Check that all expected instance settings are in place.
     $field_type = field_info_field_types($field_definition['type']);
-    $this->assertEqual($instance['settings'], $field_type['instance_settings'] , 'All expected instance settings are present.');
+    $this->assertEqual($instance->settings, $field_type['instance_settings'] , 'All expected instance settings are present.');
   }
 
   /**
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldInstanceCrudTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldInstanceCrudTest.php
index 5f9578a..00cddde 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldInstanceCrudTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldInstanceCrudTest.php
@@ -31,7 +31,7 @@ function setUp() {
     );
     field_create_field($this->field);
     $this->instance_definition = array(
-      'field_name' => $this->field['field_name'],
+      'field_name' => $this->field->id(),
       'entity_type' => 'test_entity',
       'bundle' => 'test_bundle',
     );
@@ -95,8 +95,8 @@ function testCreateFieldInstance() {
     // by the field.
     try {
       $instance = $this->instance_definition;
-      $instance['field_name'] = $field_restricted['field_name'];
-      $instance['entity_type'] = 'test_cacheable_entity';
+      $instance->id = $field_restricted['field_name'];
+      $instance->entity_type = 'test_cacheable_entity';
       field_create_instance($instance);
       $this->pass(t('Can create an instance on an entity type allowed by the field.'));
     }
@@ -108,7 +108,7 @@ function testCreateFieldInstance() {
     // forbidden by the field.
     try {
       $instance = $this->instance_definition;
-      $instance['field_name'] = $field_restricted['field_name'];
+      $instance->id = $field_restricted['field_name'];
       field_create_instance($instance);
       $this->fail(t('Cannot create an instance on an entity type forbidden by the field.'));
     }
@@ -127,9 +127,9 @@ function testReadFieldInstance() {
 
     // Read the instance back.
     $instance = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']);
-    $this->assertTrue($this->instance_definition['field_name'] == $instance['field_name'], 'The field was properly read.');
-    $this->assertTrue($this->instance_definition['entity_type'] == $instance['entity_type'], 'The field was properly read.');
-    $this->assertTrue($this->instance_definition['bundle'] == $instance['bundle'], 'The field was properly read.');
+    $this->assertTrue($this->instance_definition['field_name'] == $instance->getFieldName(), 'The field was properly read.');
+    $this->assertTrue($this->instance_definition['entity_type'] == $instance->entity_type, 'The field was properly read.');
+    $this->assertTrue($this->instance_definition['bundle'] == $instance->bundle, 'The field was properly read.');
   }
 
   /**
@@ -140,16 +140,16 @@ function testUpdateFieldInstance() {
 
     // Check that basic changes are saved.
     $instance = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']);
-    $instance['required'] = !$instance['required'];
-    $instance['label'] = $this->randomName();
-    $instance['description'] = $this->randomName();
-    $instance['settings']['test_instance_setting'] = $this->randomName();
+    $instance->required = !$instance->required;
+    $instance->label = $this->randomName();
+    $instance->description = $this->randomName();
+    $instance->settings['test_instance_setting'] = $this->randomName();
     field_update_instance($instance);
 
     $instance_new = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']);
-    $this->assertEqual($instance['required'], $instance_new['required'], '"required" change is saved');
-    $this->assertEqual($instance['label'], $instance_new['label'], '"label" change is saved');
-    $this->assertEqual($instance['description'], $instance_new['description'], '"description" change is saved');
+    $this->assertEqual($instance->required, $instance_new->required, '"required" change is saved');
+    $this->assertEqual($instance->label(), $instance_new->label(), '"label" change is saved');
+    $this->assertEqual($instance->description, $instance_new->description, '"description" change is saved');
 
     // TODO: test failures.
   }
@@ -171,13 +171,13 @@ function testDeleteFieldInstance() {
 
     // Test that the first instance is not deleted, and then delete it.
     $instance = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle'], array('include_deleted' => TRUE));
-    $this->assertTrue(!empty($instance) && empty($instance['deleted']), 'A new field instance is not marked for deletion.');
+    $this->assertTrue(!empty($instance) && empty($instance->deleted), 'A new field instance is not marked for deletion.');
     field_delete_instance($instance);
 
     // Make sure the instance is marked as deleted when the instance is
     // specifically loaded.
     $instance = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle'], array('include_deleted' => TRUE));
-    $this->assertTrue(!empty($instance['deleted']), 'A deleted field instance is marked for deletion.');
+    $this->assertTrue(!empty($instance->deleted), 'A deleted field instance is marked for deletion.');
 
     // Try to load the instance normally and make sure it does not show up.
     $instance = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']);
@@ -185,13 +185,13 @@ function testDeleteFieldInstance() {
 
     // Make sure the other field instance is not deleted.
     $another_instance = field_read_instance('test_entity', $this->another_instance_definition['field_name'], $this->another_instance_definition['bundle']);
-    $this->assertTrue(!empty($another_instance) && empty($another_instance['deleted']), 'A non-deleted field instance is not marked for deletion.');
+    $this->assertTrue(!empty($another_instance) && empty($another_instance->deleted), 'A non-deleted field instance is not marked for deletion.');
 
     // Make sure the field is deleted when its last instance is deleted.
     field_delete_instance($another_instance);
     $deleted_fields = \Drupal::state()->get('field.field.deleted');
-    $this->assertTrue(isset($deleted_fields[$another_instance['field_id']]), 'A deleted field is marked for deletion.');
-    $field = field_read_field($another_instance['field_name']);
+    $this->assertTrue(isset($deleted_fields[$another_instance->field_uuid]), 'A deleted field is marked for deletion.');
+    $field = field_read_field($another_instance->getFieldName());
     $this->assertFalse($field, 'The field marked to be deleted is not found anymore in the configuration.');
   }
 }
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php b/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php
index ed3c151..33b1277 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php
@@ -58,7 +58,7 @@ function createFieldWithInstance($suffix = '') {
     $this->$field_name = drupal_strtolower($this->randomName() . '_field_name' . $suffix);
     $this->$field = array('field_name' => $this->$field_name, 'type' => 'test_field', 'cardinality' => 4);
     $this->$field = field_create_field($this->$field);
-    $this->$field_id = $this->{$field}['uuid'];
+    $this->$field_id = $this->{$field}->uuid;
     $this->$instance = array(
       'field_name' => $this->$field_name,
       'entity_type' => 'test_entity',
diff --git a/core/modules/field/lib/Drupal/field/Tests/FormTest.php b/core/modules/field/lib/Drupal/field/Tests/FormTest.php
index 6e20523..8a0ccab 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FormTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FormTest.php
@@ -51,11 +51,11 @@ function setUp() {
 
   function testFieldFormSingle() {
     $this->field = $this->field_single;
-    $this->field_name = $this->field['field_name'];
-    $this->instance['field_name'] = $this->field_name;
+    $this->field_name = $this->field->id();
+    $this->instance->id = $this->field_name;
     field_create_field($this->field);
     field_create_instance($this->instance);
-    entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default')
+    entity_get_form_display($this->instance->entity_type, $this->instance->bundle, 'default')
       ->setComponent($this->field_name)
       ->save();
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
@@ -76,7 +76,7 @@ function testFieldFormSingle() {
     // Submit with invalid value (field-level validation).
     $edit = array("{$this->field_name}[$langcode][0][value]" => -1);
     $this->drupalPost(NULL, $edit, t('Save'));
-    $this->assertRaw(t('%name does not accept the value -1.', array('%name' => $this->instance['label'])), 'Field validation fails with invalid input.');
+    $this->assertRaw(t('%name does not accept the value -1.', array('%name' => $this->instance->label())), 'Field validation fails with invalid input.');
     // TODO : check that the correct field is flagged for error.
 
     // Create an entity
@@ -118,13 +118,13 @@ function testFieldFormSingle() {
    */
   function testFieldFormDefaultValue() {
     $this->field = $this->field_single;
-    $this->field_name = $this->field['field_name'];
-    $this->instance['field_name'] = $this->field_name;
+    $this->field_name = $this->field->id();
+    $this->instance->id = $this->field_name;
     $default = rand(1, 127);
-    $this->instance['default_value'] = array(array('value' => $default));
+    $this->instance->default_value = array(array('value' => $default));
     field_create_field($this->field);
     field_create_instance($this->instance);
-    entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default')
+    entity_get_form_display($this->instance->entity_type, $this->instance->bundle, 'default')
       ->setComponent($this->field_name)
       ->save();
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
@@ -146,12 +146,12 @@ function testFieldFormDefaultValue() {
 
   function testFieldFormSingleRequired() {
     $this->field = $this->field_single;
-    $this->field_name = $this->field['field_name'];
-    $this->instance['field_name'] = $this->field_name;
-    $this->instance['required'] = TRUE;
+    $this->field_name = $this->field->id();
+    $this->instance->id = $this->field_name;
+    $this->instance->required = TRUE;
     field_create_field($this->field);
     field_create_instance($this->instance);
-    entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default')
+    entity_get_form_display($this->instance->entity_type, $this->instance->bundle, 'default')
       ->setComponent($this->field_name)
       ->save();
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
@@ -159,7 +159,7 @@ function testFieldFormSingleRequired() {
     // Submit with missing required value.
     $edit = array();
     $this->drupalPost('test-entity/add/test_bundle', $edit, t('Save'));
-    $this->assertRaw(t('!name field is required.', array('!name' => $this->instance['label'])), 'Required field with no value fails validation');
+    $this->assertRaw(t('!name field is required.', array('!name' => $this->instance->label())), 'Required field with no value fails validation');
 
     // Create an entity
     $value = mt_rand(1, 127);
@@ -175,24 +175,24 @@ function testFieldFormSingleRequired() {
     $value = '';
     $edit = array("{$this->field_name}[$langcode][0][value]" => $value);
     $this->drupalPost('test-entity/manage/' . $id . '/edit', $edit, t('Save'));
-    $this->assertRaw(t('!name field is required.', array('!name' => $this->instance['label'])), 'Required field with no value fails validation');
+    $this->assertRaw(t('!name field is required.', array('!name' => $this->instance->label())), 'Required field with no value fails validation');
   }
 
 //  function testFieldFormMultiple() {
 //    $this->field = $this->field_multiple;
-//    $this->field_name = $this->field['field_name'];
-//    $this->instance['field_name'] = $this->field_name;
+//    $this->field_name = $this->field->id();
+//    $this->instance->id = $this->field_name;
 //    field_create_field($this->field);
 //    field_create_instance($this->instance);
 //  }
 
   function testFieldFormUnlimited() {
     $this->field = $this->field_unlimited;
-    $this->field_name = $this->field['field_name'];
-    $this->instance['field_name'] = $this->field_name;
+    $this->field_name = $this->field->id();
+    $this->instance->id = $this->field_name;
     field_create_field($this->field);
     field_create_instance($this->instance);
-    entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default')
+    entity_get_form_display($this->instance->entity_type, $this->instance->bundle, 'default')
       ->setComponent($this->field_name)
       ->save();
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
@@ -271,11 +271,11 @@ function testFieldFormUnlimited() {
   function testFieldFormMultivalueWithRequiredRadio() {
     // Create a multivalue test field.
     $this->field = $this->field_unlimited;
-    $this->field_name = $this->field['field_name'];
-    $this->instance['field_name'] = $this->field_name;
+    $this->field_name = $this->field->id();
+    $this->instance->id = $this->field_name;
     field_create_field($this->field);
     field_create_instance($this->instance);
-    entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default')
+    entity_get_form_display($this->instance->entity_type, $this->instance->bundle, 'default')
       ->setComponent($this->field_name)
       ->save();
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
@@ -295,8 +295,8 @@ function testFieldFormMultivalueWithRequiredRadio() {
       'required' => TRUE,
     );
     field_create_instance($instance);
-    entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')
-      ->setComponent($instance['field_name'], array(
+    entity_get_form_display($instance->entity_type, $instance->bundle, 'default')
+      ->setComponent($instance->getFieldName(), array(
         'type' => 'options_buttons',
       ))
       ->save();
@@ -318,11 +318,11 @@ function testFieldFormMultivalueWithRequiredRadio() {
 
   function testFieldFormJSAddMore() {
     $this->field = $this->field_unlimited;
-    $this->field_name = $this->field['field_name'];
-    $this->instance['field_name'] = $this->field_name;
+    $this->field_name = $this->field->id();
+    $this->instance->id = $this->field_name;
     field_create_field($this->field);
     field_create_instance($this->instance);
-    entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default')
+    entity_get_form_display($this->instance->entity_type, $this->instance->bundle, 'default')
       ->setComponent($this->field_name)
       ->save();
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
@@ -380,11 +380,11 @@ function testFieldFormMultipleWidget() {
     // Create a field with fixed cardinality and an instance using a multiple
     // widget.
     $this->field = $this->field_multiple;
-    $this->field_name = $this->field['field_name'];
-    $this->instance['field_name'] = $this->field_name;
+    $this->field_name = $this->field->id();
+    $this->instance->id = $this->field_name;
     field_create_field($this->field);
     field_create_instance($this->instance);
-    entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default')
+    entity_get_form_display($this->instance->entity_type, $this->instance->bundle, 'default')
       ->setComponent($this->field_name, array(
         'type' => 'test_field_widget_multiple',
       ))
@@ -423,12 +423,12 @@ function testFieldFormMultipleWidget() {
   function testFieldFormAccess() {
     // Create a "regular" field.
     $field = $this->field_single;
-    $field_name = $field['field_name'];
+    $field_name = $field->id();
     $instance = $this->instance;
-    $instance['field_name'] = $field_name;
+    $instance->id = $field_name;
     field_create_field($field);
     field_create_instance($instance);
-    entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default')
+    entity_get_form_display($this->instance->entity_type, $this->instance->bundle, 'default')
       ->setComponent($field_name)
       ->save();
 
@@ -455,11 +455,11 @@ function testFieldFormAccess() {
     // Test that the form structure includes full information for each delta
     // apart from #access.
     $entity_type = 'test_entity';
-    $entity = field_test_create_entity(0, 0, $this->instance['bundle']);
+    $entity = field_test_create_entity(0, 0, $this->instance->bundle);
 
     $form = array();
     $form_state = form_state_defaults();
-    $form_state['form_display'] = entity_get_form_display($entity_type, $this->instance['bundle'], 'default');
+    $form_state['form_display'] = entity_get_form_display($entity_type, $this->instance->bundle, 'default');
     field_attach_form($entity, $form, $form_state);
 
     $this->assertEqual($form[$field_name_no_access][$langcode][0]['value']['#entity_type'], $entity_type, 'The correct entity type is set in the field structure.');
@@ -503,17 +503,17 @@ function testNestedFieldForm() {
     // Add two instances on the 'test_bundle'
     field_create_field($this->field_single);
     field_create_field($this->field_unlimited);
-    $this->instance['field_name'] = 'field_single';
-    $this->instance['label'] = 'Single field';
+    $this->instance->id = 'field_single';
+    $this->instance->label = 'Single field';
     field_create_instance($this->instance);
-    entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default')
-      ->setComponent($this->instance['field_name'])
+    entity_get_form_display($this->instance->entity_type, $this->instance->bundle, 'default')
+      ->setComponent($this->instance->getFieldName())
       ->save();
-    $this->instance['field_name'] = 'field_unlimited';
-    $this->instance['label'] = 'Unlimited field';
+    $this->instance->id = 'field_unlimited';
+    $this->instance->label = 'Unlimited field';
     field_create_instance($this->instance);
-    entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default')
-      ->setComponent($this->instance['field_name'])
+    entity_get_form_display($this->instance->entity_type, $this->instance->bundle, 'default')
+      ->setComponent($this->instance->getFieldName())
       ->save();
 
     // Create two entities.
@@ -616,13 +616,13 @@ function testNestedFieldForm() {
    */
   function testFieldFormHiddenWidget() {
     $this->field = $this->field_single;
-    $this->field_name = $this->field['field_name'];
-    $this->instance['field_name'] = $this->field_name;
-    $this->instance['default_value'] = array(0 => array('value' => 99));
+    $this->field_name = $this->field->id();
+    $this->instance->id = $this->field_name;
+    $this->instance->default_value = array(0 => array('value' => 99));
     field_create_field($this->field);
     field_create_instance($this->instance);
-    entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default')
-      ->setComponent($this->instance['field_name'], array(
+    entity_get_form_display($this->instance->entity_type, $this->instance->bundle, 'default')
+      ->setComponent($this->instance->getFieldName(), array(
         'type' => 'hidden',
       ))
       ->save();
@@ -643,10 +643,10 @@ function testFieldFormHiddenWidget() {
 
     // Update the instance to remove the default value and switch to the
     // default widget.
-    $this->instance['default_value'] = NULL;
+    $this->instance->default_value = NULL;
     field_update_instance($this->instance);
-    entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default')
-      ->setComponent($this->instance['field_name'], array(
+    entity_get_form_display($this->instance->entity_type, $this->instance->bundle, 'default')
+      ->setComponent($this->instance->getFieldName(), array(
         'type' => 'test_field_widget',
       ))
       ->save();
@@ -665,8 +665,8 @@ function testFieldFormHiddenWidget() {
     $this->assertEqual($entity->{$this->field_name}[$langcode][0]['value'], $value, 'Field value was updated');
 
     // Update the form display and switch to the Hidden widget again.
-    entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default')
-      ->setComponent($this->instance['field_name'], array(
+    entity_get_form_display($this->instance->entity_type, $this->instance->bundle, 'default')
+      ->setComponent($this->instance->getFieldName(), array(
         'type' => 'hidden',
       ))
       ->save();
diff --git a/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php b/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php
index ae52f2e..4e45230 100644
--- a/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php
@@ -76,7 +76,7 @@ function testFieldAvailableLanguages() {
     // Test 'translatable' fieldable info.
     field_test_entity_info_translatable('test_entity', FALSE);
     $field = clone($this->field);
-    $field['field_name'] .= '_untranslatable';
+    $field->id .= '_untranslatable';
 
     // Enable field translations for the entity.
     field_test_entity_info_translatable('test_entity', TRUE);
@@ -94,7 +94,7 @@ function testFieldAvailableLanguages() {
     $this->assertFalse(in_array('en', $available_langcodes), format_string('%language was made unavailable.', array('%language' => 'en')));
 
     // Test field_available_languages() behavior for untranslatable fields.
-    $this->field['translatable'] = FALSE;
+    $this->field->translatable = FALSE;
     field_update_field($this->field);
     $available_langcodes = field_available_languages($this->entity_type, $this->field);
     $this->assertTrue(count($available_langcodes) == 1 && $available_langcodes[0] === Language::LANGCODE_NOT_SPECIFIED, 'For untranslatable fields only Language::LANGCODE_NOT_SPECIFIED is available.');
@@ -108,7 +108,7 @@ function testFieldInvoke() {
     field_test_entity_info_translatable('test_entity', TRUE);
 
     $entity_type = 'test_entity';
-    $entity = field_test_create_entity(0, 0, $this->instance['bundle']);
+    $entity = field_test_create_entity(0, 0, $this->instance->bundle);
 
     // Populate some extra languages to check if _field_invoke() correctly uses
     // the result of field_available_languages().
@@ -121,7 +121,7 @@ function testFieldInvoke() {
 
     // For each given language provide some random values.
     foreach ($langcodes as $langcode) {
-      for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
+      for ($delta = 0; $delta < $this->field->cardinality; $delta++) {
         $values[$langcode][$delta]['value'] = mt_rand(1, 127);
       }
     }
@@ -153,7 +153,7 @@ function testFieldInvokeMultiple() {
     $available_langcodes = field_available_languages($this->entity_type, $this->field);
 
     for ($id = 1; $id <= $entity_count; ++$id) {
-      $entity = field_test_create_entity($id, $id, $this->instance['bundle']);
+      $entity = field_test_create_entity($id, $id, $this->instance->bundle);
       $langcodes = $available_langcodes;
 
       // Populate some extra languages to check whether _field_invoke()
@@ -171,7 +171,7 @@ function testFieldInvokeMultiple() {
         // per-entity language suggestions work even when available field values
         // are different for each language.
         if ($i !== $id) {
-          for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
+          for ($delta = 0; $delta < $this->field->cardinality; $delta++) {
             $values[$id][$langcode][$delta]['value'] = mt_rand(1, 127);
           }
         }
@@ -224,12 +224,12 @@ function testTranslatableFieldSaveLoad() {
     field_test_entity_info_translatable('test_entity', TRUE);
     $eid = $evid = 1;
     $entity_type = 'test_entity';
-    $entity = field_test_create_entity($eid, $evid, $this->instance['bundle']);
+    $entity = field_test_create_entity($eid, $evid, $this->instance->bundle);
     $field_translations = array();
     $available_langcodes = field_available_languages($entity_type, $this->field);
     $this->assertTrue(count($available_langcodes) > 1, 'Field is translatable.');
     foreach ($available_langcodes as $langcode) {
-      $field_translations[$langcode] = $this->_generateTestFieldValues($this->field['cardinality']);
+      $field_translations[$langcode] = $this->_generateTestFieldValues($this->field->cardinality);
     }
 
     // Save and reload the field translations.
@@ -264,9 +264,9 @@ function testTranslatableFieldSaveLoad() {
 
     $eid++;
     $evid++;
-    $values = array('eid' => $eid, 'evid' => $evid, 'fttype' => $instance['bundle'], 'langcode' => $translation_langcodes[0]);
+    $values = array('eid' => $eid, 'evid' => $evid, 'fttype' => $instance->bundle, 'langcode' => $translation_langcodes[0]);
     foreach ($translation_langcodes as $langcode) {
-      $values[$this->field_name][$langcode] = $this->_generateTestFieldValues($this->field['cardinality']);
+      $values[$this->field_name][$langcode] = $this->_generateTestFieldValues($this->field->cardinality);
     }
     $entity = entity_create($entity_type, $values);
 
@@ -275,16 +275,16 @@ function testTranslatableFieldSaveLoad() {
     $this->assertEqual($translation_langcodes, $field_langcodes, 'Missing translations did not get a default value.');
 
     foreach ($entity->{$field_name_default} as $langcode => $items) {
-      $this->assertEqual($items, $instance['default_value'], format_string('Default value correctly populated for language %language.', array('%language' => $langcode)));
+      $this->assertEqual($items, $instance->default_value, format_string('Default value correctly populated for language %language.', array('%language' => $langcode)));
     }
 
     // Check that explicit empty values are not overridden with default values.
     foreach (array(NULL, array()) as $empty_items) {
       $eid++;
       $evid++;
-      $values = array('eid' => $eid, 'evid' => $evid, 'fttype' => $instance['bundle'], 'langcode' => $translation_langcodes[0]);
+      $values = array('eid' => $eid, 'evid' => $evid, 'fttype' => $instance->bundle, 'langcode' => $translation_langcodes[0]);
       foreach ($translation_langcodes as $langcode) {
-        $values[$this->field_name][$langcode] = $this->_generateTestFieldValues($this->field['cardinality']);
+        $values[$this->field_name][$langcode] = $this->_generateTestFieldValues($this->field->cardinality);
         $values[$field_name_default][$langcode] = $empty_items;
       }
       $entity = entity_create($entity_type, $values);
@@ -313,14 +313,14 @@ function testFieldDisplayLanguage() {
     field_create_field($field);
 
     $instance = array(
-      'field_name' => $field['field_name'],
+      'field_name' => $field->id(),
       'entity_type' => $entity_type,
       'bundle' => 'test_bundle',
     );
     field_create_instance($instance);
 
-    $entity = field_test_create_entity(1, 1, $this->instance['bundle']);
-    $instances = field_info_instances($entity_type, $this->instance['bundle']);
+    $entity = field_test_create_entity(1, 1, $this->instance->bundle);
+    $instances = field_info_instances($entity_type, $this->instance->bundle);
 
     $enabled_langcodes = field_content_languages();
     $langcodes = array();
@@ -331,7 +331,7 @@ function testFieldDisplayLanguage() {
     // Generate field translations for languages different from the first
     // enabled.
     foreach ($instances as $instance) {
-      $field_name = $instance['field_name'];
+      $field_name = $instance->getFieldName();
       $field = field_info_field($field_name);
       do {
         // Index 0 is reserved for the requested language, this way we ensure
@@ -340,7 +340,7 @@ function testFieldDisplayLanguage() {
       }
       while (isset($langcodes[$langcode]));
       $langcodes[$langcode] = TRUE;
-      $entity->{$field_name}[$langcode] = $this->_generateTestFieldValues($field['cardinality']);
+      $entity->{$field_name}[$langcode] = $this->_generateTestFieldValues($field->cardinality);
       // If the langcode is one of the locked languages, then that one
       // will also be used for display. Otherwise, the default one should be
       // used, which is Language::LANGCODE_NOT_SPECIFIED.
@@ -358,7 +358,7 @@ function testFieldDisplayLanguage() {
     $requested_langcode = $enabled_langcodes[0];
     $display_langcodes = field_language($entity, NULL, $requested_langcode);
     foreach ($instances as $instance) {
-      $field_name = $instance['field_name'];
+      $field_name = $instance->getFieldName();
       $this->assertTrue($display_langcodes[$field_name] == $locked_languages[$field_name], format_string('The display language for field %field_name is %language.', array('%field_name' => $field_name, '%language' => $locked_languages[$field_name])));
     }
 
@@ -367,7 +367,7 @@ function testFieldDisplayLanguage() {
     drupal_static_reset('field_language');
     $display_langcodes = field_language($entity, NULL, $requested_langcode);
     foreach ($instances as $instance) {
-      $field_name = $instance['field_name'];
+      $field_name = $instance->getFieldName();
       $langcode = $display_langcodes[$field_name];
       // As the requested language was not assinged to any field, if the
       // returned language is defined for the current field, core fallback rules
diff --git a/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php b/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php
index 786f1b4..db2c927 100644
--- a/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php
@@ -76,10 +76,10 @@ function testFieldFormTranslationRevisions() {
     // Prepare the field translations.
     field_test_entity_info_translatable($this->entity_type, TRUE);
     $eid = 1;
-    $entity = field_test_create_entity($eid, $eid, $this->instance['bundle']);
+    $entity = field_test_create_entity($eid, $eid, $this->instance->bundle);
     $available_langcodes = array_flip(field_available_languages($this->entity_type, $this->field));
     unset($available_langcodes[Language::LANGCODE_NOT_SPECIFIED]);
-    $field_name = $this->field['field_name'];
+    $field_name = $this->field->id();
 
     // Store the field translations.
     $entity->enforceIsNew();
@@ -103,7 +103,7 @@ function testFieldFormTranslationRevisions() {
    * by the passed arguments were correctly stored.
    */
   private function checkTranslationRevisions($eid, $evid, $available_langcodes) {
-    $field_name = $this->field['field_name'];
+    $field_name = $this->field->id();
     $entity = field_test_entity_test_load($eid, $evid);
     foreach ($available_langcodes as $langcode => $value) {
       $passed = isset($entity->{$field_name}[$langcode]) && $entity->{$field_name}[$langcode][0]['value'] == $value + 1;
diff --git a/core/modules/field/lib/Drupal/field/Tests/Views/FieldTestBase.php b/core/modules/field/lib/Drupal/field/Tests/Views/FieldTestBase.php
index c0f500b..788dced 100644
--- a/core/modules/field/lib/Drupal/field/Tests/Views/FieldTestBase.php
+++ b/core/modules/field/lib/Drupal/field/Tests/Views/FieldTestBase.php
@@ -66,7 +66,7 @@ function setUpFields($amount = 3) {
   function setUpInstances($bundle = 'page') {
     foreach ($this->fields as $key => $field) {
       $instance = array(
-        'field_name' => $field['field_name'],
+        'field_name' => $field->id(),
         'entity_type' => 'node',
         'bundle' => 'page',
       );
diff --git a/core/modules/field/lib/Drupal/field/Tests/Views/HandlerFieldFieldTest.php b/core/modules/field/lib/Drupal/field/Tests/Views/HandlerFieldFieldTest.php
index f365635..cbcef43 100644
--- a/core/modules/field/lib/Drupal/field/Tests/Views/HandlerFieldFieldTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/Views/HandlerFieldFieldTest.php
@@ -60,13 +60,13 @@ protected function setUp() {
 
       for ($key = 0; $key < 3; $key++) {
         $field = $this->fields[$key];
-        $edit[$field['field_name']][0]['value'] = $this->randomName(8);
+        $edit[$field->id()][0]['value'] = $this->randomName(8);
       }
       for ($j = 0; $j < 5; $j++) {
-        $edit[$this->fields[3]['field_name']][$j]['value'] = $this->randomName(8);
+        $edit[$this->fields[3]->id()][$j]['value'] = $this->randomName(8);
       }
       // Set this field to be empty.
-      $edit[$this->fields[4]['field_name']] = array(array('value' => NULL));
+      $edit[$this->fields[4]->id()] = array(array('value' => NULL));
 
       $this->nodes[$i] = $this->drupalCreateNode($edit);
     }
@@ -83,9 +83,9 @@ protected function setUp() {
   protected function prepareView(ViewExecutable $view) {
     $view->initDisplay();
     foreach ($this->fields as $key => $field) {
-      $view->display_handler->options['fields'][$field['field_name']]['id'] = $field['field_name'];
-      $view->display_handler->options['fields'][$field['field_name']]['table'] = 'field_data_' . $field['field_name'];
-      $view->display_handler->options['fields'][$field['field_name']]['field'] = $field['field_name'];
+      $view->display_handler->options['fields'][$field->id()]['id'] = $field->id();
+      $view->display_handler->options['fields'][$field->id()]['table'] = 'field_data_' . $field->id();
+      $view->display_handler->options['fields'][$field->id()]['field'] = $field->id();
     }
   }
 
@@ -104,8 +104,8 @@ public function _testSimpleFieldRender() {
     for ($i = 0; $i < 3; $i++) {
       for ($key = 0; $key < 2; $key++) {
         $field = $this->fields[$key];
-        $rendered_field = $view->style_plugin->getField($i, $field['field_name']);
-        $expected_field = $this->nodes[$i]->{$field['field_name']}[Language::LANGCODE_NOT_SPECIFIED][0]['value'];
+        $rendered_field = $view->style_plugin->getField($i, $field->id());
+        $expected_field = $this->nodes[$i]->{$field->id()}[Language::LANGCODE_NOT_SPECIFIED][0]['value'];
         $this->assertEqual($rendered_field, $expected_field);
       }
     }
diff --git a/core/modules/field/tests/modules/field_test/field_test.field.inc b/core/modules/field/tests/modules/field_test/field_test.field.inc
index 0ff40e7..1384f17 100644
--- a/core/modules/field/tests/modules/field_test/field_test.field.inc
+++ b/core/modules/field/tests/modules/field_test/field_test.field.inc
@@ -65,7 +65,7 @@ function field_test_field_widget_info_alter(&$info) {
  * Implements hook_field_update_forbid().
  */
 function field_test_field_update_forbid($field, $prior_field) {
-  if ($field['type'] == 'test_field' && $field['settings']['unchangeable'] != $prior_field['settings']['unchangeable']) {
+  if ($field->type == 'test_field' && $field->settings['unchangeable'] != $prior_field->settings['unchangeable']) {
     throw new FieldException("field_test 'unchangeable' setting cannot be changed'");
   }
 }
@@ -80,7 +80,7 @@ function field_test_field_load($entity_type, $entities, $field, $instances, $lan
   foreach ($items as $id => $item) {
     // To keep the test non-intrusive, only act for instances with the
     // test_hook_field_load setting explicitly set to TRUE.
-    if (!empty($instances[$id]['settings']['test_hook_field_load'])) {
+    if (!empty($instances[$id]->settings['test_hook_field_load'])) {
       foreach ($item as $delta => $value) {
         // Don't add anything on empty values.
         if ($value) {
@@ -127,9 +127,9 @@ function field_test_field_validate(EntityInterface $entity = NULL, $field, $inst
 
   foreach ($items as $delta => $item) {
     if ($item['value'] == -1) {
-      $errors[$field['field_name']][$langcode][$delta][] = array(
+      $errors[$field->id()][$langcode][$delta][] = array(
         'error' => 'field_test_invalid',
-        'message' => t('%name does not accept the value -1.', array('%name' => $instance['label'])),
+        'message' => t('%name does not accept the value -1.', array('%name' => $instance->label())),
       );
     }
   }
@@ -146,7 +146,7 @@ function field_test_field_is_empty($item, $field_type) {
  * Implements hook_field_settings_form().
  */
 function field_test_field_settings_form($field, $instance) {
-  $settings = $field['settings'];
+  $settings = $field->settings;
 
   $form['test_field_setting'] = array(
     '#type' => 'textfield',
@@ -163,7 +163,7 @@ function field_test_field_settings_form($field, $instance) {
  * Implements hook_field_instance_settings_form().
  */
 function field_test_field_instance_settings_form($field, $instance) {
-  $settings = $instance['settings'];
+  $settings = $instance->settings;
 
   $form['test_instance_setting'] = array(
     '#type' => 'textfield',
@@ -199,13 +199,13 @@ function field_test_default_value(EntityInterface $entity, $field, $instance) {
  * Implements hook_field_access().
  */
 function field_test_field_access($op, FieldInterface $field, $entity_type, $entity, $account) {
-  if ($field['field_name'] == "field_no_{$op}_access") {
+  if ($field->id() == "field_no_{$op}_access") {
     return FALSE;
   }
 
   // Only grant view access to test_view_field fields when the user has
   // 'view test_view_field content' permission.
-  if ($field['field_name'] == 'test_view_field' && $op == 'view' && !user_access('view test_view_field content')) {
+  if ($field->id() == 'test_view_field' && $op == 'view' && !user_access('view test_view_field content')) {
     return FALSE;
   }
 
diff --git a/core/modules/field/tests/modules/field_test/field_test.install b/core/modules/field/tests/modules/field_test/field_test.install
index b0a15a2..8300ce9 100644
--- a/core/modules/field/tests/modules/field_test/field_test.install
+++ b/core/modules/field/tests/modules/field_test/field_test.install
@@ -114,7 +114,7 @@ function field_test_schema() {
  * Implements hook_field_schema().
  */
 function field_test_field_schema($field) {
-  if ($field['type'] == 'test_field') {
+  if ($field->type == 'test_field') {
     return array(
       'columns' => array(
         'value' => array(
@@ -131,13 +131,13 @@ function field_test_field_schema($field) {
   else {
     $foreign_keys = array();
     // The 'foreign keys' key is not always used in tests.
-    if (!empty($field['settings']['foreign_key_name'])) {
+    if (!empty($field->settings['foreign_key_name'])) {
       $foreign_keys['foreign keys'] = array(
         // This is a dummy foreign key definition, references a table that
         // doesn't exist, but that's not a problem.
-        $field['settings']['foreign_key_name'] => array(
-          'table' => $field['settings']['foreign_key_name'],
-          'columns' => array($field['settings']['foreign_key_name'] => 'id'),
+        $field->settings['foreign_key_name'] => array(
+          'table' => $field->settings['foreign_key_name'],
+          'columns' => array($field->settings['foreign_key_name'] => 'id'),
         ),
       );
     }
diff --git a/core/modules/field/tests/modules/field_test/field_test.module b/core/modules/field/tests/modules/field_test/field_test.module
index 04f1c83..74103136 100644
--- a/core/modules/field/tests/modules/field_test/field_test.module
+++ b/core/modules/field/tests/modules/field_test/field_test.module
@@ -80,7 +80,7 @@ function field_test_menu() {
  * This simulates a field operation callback to be invoked by _field_invoke().
  */
 function field_test_field_test_op(EntityInterface $entity, $field, $instance, $langcode, &$items) {
-  return array($langcode => hash('sha256', serialize(array($entity, $field['field_name'], $langcode, $items))));
+  return array($langcode => hash('sha256', serialize(array($entity, $field->id(), $langcode, $items))));
 }
 
 /**
@@ -96,7 +96,7 @@ function field_test_field_test_op_multiple($entity_type, $entities, $field, $ins
     // language. To verify this we try to access all the passed data structures
     // by entity id. If they are grouped correctly, one entity, one instance and
     // one array of items should be available for each entity id.
-    $field_name = $instances[$id]['field_name'];
+    $field_name = $instances[$id]->getFieldName();
     $result[$id] = array($langcode => hash('sha256', serialize(array($entity_type, $entity, $field_name, $langcode, $items[$id]))));
   }
   return $result;
diff --git a/core/modules/field/tests/modules/field_test/field_test.storage.inc b/core/modules/field/tests/modules/field_test/field_test.storage.inc
index d3a7f82..07b73e6 100644
--- a/core/modules/field/tests/modules/field_test/field_test.storage.inc
+++ b/core/modules/field/tests/modules/field_test/field_test.storage.inc
@@ -31,7 +31,7 @@ function field_test_field_storage_details($field) {
 
   // Add field columns.
   $columns = array();
-  foreach ((array) $field['columns'] as $column_name => $attributes) {
+  foreach ((array) $field->getSchema('columns') as $column_name => $attributes) {
     $columns[$column_name] = $column_name;
   }
   return array(
@@ -50,9 +50,9 @@ function field_test_field_storage_details($field) {
 function field_test_field_storage_details_alter(&$details, $field) {
 
   // For testing, storage details are changed only because of the field name.
-  if ($field['field_name'] == 'field_test_change_my_details') {
+  if ($field->id() == 'field_test_change_my_details') {
     $columns = array();
-    foreach ((array) $field['columns'] as $column_name => $attributes) {
+    foreach ((array) $field->getSchema('columns') as $column_name => $attributes) {
       $columns[$column_name] = $column_name;
     }
     $details['drupal_variables'] = array(
@@ -88,8 +88,8 @@ function field_test_field_storage_load($entity_type, $entities, $age, $fields, $
 
   foreach ($fields as $field_id => $ids) {
     $field = field_info_field_by_id($field_id);
-    $field_name = $field['field_name'];
-    $field_data = $data[$field['uuid']];
+    $field_name = $field->id();
+    $field_data = $data[$field->uuid];
     $sub_table = $load_current ? 'current' : 'revisions';
     $delta_count = array();
     foreach ($field_data[$sub_table] as $row) {
@@ -99,9 +99,9 @@ function field_test_field_storage_load($entity_type, $entities, $age, $fields, $
             if (!isset($delta_count[$row->entity_id][$row->langcode])) {
               $delta_count[$row->entity_id][$row->langcode] = 0;
             }
-            if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$row->langcode] < $field['cardinality']) {
+            if ($field->cardinality == FIELD_CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$row->langcode] < $field->cardinality) {
               $item = array();
-              foreach ($field['columns'] as $column => $attributes) {
+              foreach ($field->getSchema('columns') as $column => $attributes) {
                 $item[$column] = $row->{$column};
               }
               $entities[$row->entity_id]->{$field_name}[$row->langcode][] = $item;
@@ -126,7 +126,7 @@ function field_test_field_storage_write(EntityInterface $entity, $op, $fields) {
 
   foreach ($fields as $field_id) {
     $field = field_info_field_by_id($field_id);
-    $field_name = $field['field_name'];
+    $field_name = $field->id();
     $field_data = &$data[$field_id];
 
     $all_langcodes = field_available_languages($entity->entityType(), $field);
@@ -167,7 +167,7 @@ function field_test_field_storage_write(EntityInterface $entity, $op, $fields) {
           'deleted' => FALSE,
           'langcode' => $langcode,
         );
-        foreach ($field['columns'] as $column => $attributes) {
+        foreach ($field->getSchema('columns') as $column => $attributes) {
           $row->{$column} = isset($item[$column]) ? $item[$column] : NULL;
         }
 
@@ -176,7 +176,7 @@ function field_test_field_storage_write(EntityInterface $entity, $op, $fields) {
           $field_data['revisions'][] = $row;
         }
 
-        if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED && ++$delta_count == $field['cardinality']) {
+        if ($field->cardinality != FIELD_CARDINALITY_UNLIMITED && ++$delta_count == $field->cardinality) {
           break;
         }
       }
@@ -193,8 +193,8 @@ function field_test_field_storage_delete(EntityInterface $entity, $fields) {
   // Note: reusing field_test_storage_purge(), like field_sql_storage.module
   // does, is highly inefficient in our case...
   foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) {
-    if (isset($fields[$instance['field_id']])) {
-      $field = field_info_field_by_id($instance['field_id']);
+    if (isset($fields[$instance->field_uuid])) {
+      $field = field_info_field_by_id($instance->field_uuid);
       field_test_field_storage_purge($entity, $field, $instance);
     }
   }
@@ -206,7 +206,7 @@ function field_test_field_storage_delete(EntityInterface $entity, $fields) {
 function field_test_field_storage_purge(EntityInterface $entity, $field, $instance) {
   $data = _field_test_storage_data();
 
-  $field_data = &$data[$field['uuid']];
+  $field_data = &$data[$field->uuid];
   foreach (array('current', 'revisions') as $sub_table) {
     foreach ($field_data[$sub_table] as $key => $row) {
       if ($row->type == $entity->entityType() && $row->entity_id == $entity->id()) {
@@ -247,9 +247,9 @@ function field_test_field_storage_query($field_id, $conditions, $count, &$cursor
   $load_current = $age == FIELD_LOAD_CURRENT;
 
   $field = field_info_field_by_id($field_id);
-  $field_columns = array_keys($field['columns']);
+  $field_columns = array_keys($field->getSchema('columns'));
 
-  $field_data = $data[$field['uuid']];
+  $field_data = $data[$field->uuid];
   $sub_table = $load_current ? 'current' : 'revisions';
   // We need to sort records by entity type and entity id.
   usort($field_data[$sub_table], '_field_test_field_storage_query_sort_helper');
@@ -267,7 +267,7 @@ function field_test_field_storage_query($field_id, $conditions, $count, &$cursor
       break;
     }
 
-    if ($row->field_id == $field['uuid']) {
+    if ($row->field_id == $field->uuid) {
       $match = TRUE;
       $condition_deleted = FALSE;
       // Add conditions.
@@ -366,13 +366,13 @@ function _field_test_field_storage_query_sort_helper($a, $b) {
  * Implements hook_field_storage_create_field().
  */
 function field_test_field_storage_create_field($field) {
-  if ($field['storage']['type'] == 'field_test_storage_failure') {
+  if ($field->storage['type'] == 'field_test_storage_failure') {
     throw new Exception('field_test_storage_failure engine always fails to create fields');
   }
 
   $data = _field_test_storage_data();
 
-  $data[$field['uuid']] = array(
+  $data[$field->uuid] = array(
     'current' => array(),
     'revisions' => array(),
   );
@@ -386,7 +386,7 @@ function field_test_field_storage_create_field($field) {
 function field_test_field_storage_delete_field($field) {
   $data = _field_test_storage_data();
 
-  $field_data = &$data[$field['uuid']];
+  $field_data = &$data[$field->uuid];
   foreach (array('current', 'revisions') as $sub_table) {
     foreach ($field_data[$sub_table] as &$row) {
       $row->deleted = TRUE;
@@ -402,11 +402,11 @@ function field_test_field_storage_delete_field($field) {
 function field_test_field_storage_delete_instance($instance) {
   $data = _field_test_storage_data();
 
-  $field = field_info_field($instance['field_name']);
-  $field_data = &$data[$field['uuid']];
+  $field = field_info_field($instance->getFieldName());
+  $field_data = &$data[$field->uuid];
   foreach (array('current', 'revisions') as $sub_table) {
     foreach ($field_data[$sub_table] as &$row) {
-      if ($row->bundle == $instance['bundle']) {
+      if ($row->bundle == $instance->bundle) {
         $row->deleted = TRUE;
       }
     }
@@ -424,9 +424,9 @@ function field_test_entity_bundle_rename($entity_type, $bundle_old, $bundle_new)
   // We need to account for deleted or inactive fields and instances.
   $instances = field_read_instances(array('bundle' => $bundle_new), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
   foreach ($instances as $field_name => $instance) {
-    $field = field_info_field_by_id($instance['field_id']);
-    if ($field && $field['storage']['type'] == 'field_test_storage') {
-      $field_data = &$data[$field['uuid']];
+    $field = field_info_field_by_id($instance->field_uuid);
+    if ($field && $field->storage['type'] == 'field_test_storage') {
+      $field_data = &$data[$field->uuid];
       foreach (array('current', 'revisions') as $sub_table) {
         foreach ($field_data[$sub_table] as &$row) {
           if ($row->bundle == $bundle_old) {
@@ -446,12 +446,12 @@ function field_test_entity_bundle_rename($entity_type, $bundle_old, $bundle_new)
 function field_test_field_delete_instance($instance) {
   $data = _field_test_storage_data();
 
-  $field = field_info_field($instance['field_name']);
-  if ($field['storage']['type'] == 'field_test_storage') {
-    $field_data = &$data[$field['uuid']];
+  $field = field_info_field($instance->getFieldName());
+  if ($field->storage['type'] == 'field_test_storage') {
+    $field_data = &$data[$field->uuid];
     foreach (array('current', 'revisions') as $sub_table) {
       foreach ($field_data[$sub_table] as &$row) {
-        if ($row->bundle == $instance['bundle']) {
+        if ($row->bundle == $instance->bundle) {
           $row->deleted = TRUE;
         }
       }
diff --git a/core/modules/field_sql_storage/field_sql_storage.module b/core/modules/field_sql_storage/field_sql_storage.module
index 3ccac54..dd0343d 100644
--- a/core/modules/field_sql_storage/field_sql_storage.module
+++ b/core/modules/field_sql_storage/field_sql_storage.module
@@ -50,11 +50,11 @@ function field_sql_storage_field_storage_info() {
  *   A string containing the generated name for the database table.
  */
 function _field_sql_storage_tablename($field) {
-  if ($field['deleted']) {
-    return "field_deleted_data_" . substr(hash('sha256', $field['uuid']), 0, 10);
+  if ($field->deleted) {
+    return "field_deleted_data_" . substr(hash('sha256', $field->uuid), 0, 10);
   }
   else {
-    return "field_data_{$field['field_name']}";
+    return "field_data_{$field->id()}";
   }
 }
 
@@ -73,11 +73,11 @@ function _field_sql_storage_tablename($field) {
  *   A string containing the generated name for the database table.
  */
 function _field_sql_storage_revision_tablename($field) {
-  if ($field['deleted']) {
-    return "field_deleted_revision_" . substr(hash('sha256', $field['uuid']), 0, 10);
+  if ($field->deleted) {
+    return "field_deleted_revision_" . substr(hash('sha256', $field->uuid), 0, 10);
   }
   else {
-    return "field_revision_{$field['field_name']}";
+    return "field_revision_{$field->id()}";
   }
 }
 
@@ -126,9 +126,9 @@ function _field_sql_storage_indexname($name, $index) {
  *   One or more tables representing the schema for the field.
  */
 function _field_sql_storage_schema($field) {
-  $deleted = $field['deleted'] ? 'deleted ' : '';
+  $deleted = $field->deleted ? 'deleted ' : '';
   $current = array(
-    'description' => "Data storage for {$deleted}field {$field['id']} ({$field['field_name']})",
+    'description' => "Data storage for {$deleted}field {$field->id()} ({$field->id()})",
     'fields' => array(
       'entity_type' => array(
         'type' => 'varchar',
@@ -193,41 +193,41 @@ function _field_sql_storage_schema($field) {
 
   // Add field columns.
   foreach ($schema['columns'] as $column_name => $attributes) {
-    $real_name = _field_sql_storage_columnname($field['field_name'], $column_name);
+    $real_name = _field_sql_storage_columnname($field->id(), $column_name);
     $current['fields'][$real_name] = $attributes;
   }
 
   // Add indexes.
   foreach ($schema['indexes'] as $index_name => $columns) {
-    $real_name = _field_sql_storage_indexname($field['field_name'], $index_name);
+    $real_name = _field_sql_storage_indexname($field->id(), $index_name);
     foreach ($columns as $column_name) {
       // Indexes can be specified as either a column name or an array with
       // column name and length. Allow for either case.
       if (is_array($column_name)) {
         $current['indexes'][$real_name][] = array(
-          _field_sql_storage_columnname($field['field_name'], $column_name[0]),
+          _field_sql_storage_columnname($field->id(), $column_name[0]),
           $column_name[1],
         );
       }
       else {
-        $current['indexes'][$real_name][] = _field_sql_storage_columnname($field['field_name'], $column_name);
+        $current['indexes'][$real_name][] = _field_sql_storage_columnname($field->id(), $column_name);
       }
     }
   }
 
   // Add foreign keys.
   foreach ($schema['foreign keys'] as $specifier => $specification) {
-    $real_name = _field_sql_storage_indexname($field['field_name'], $specifier);
+    $real_name = _field_sql_storage_indexname($field->id(), $specifier);
     $current['foreign keys'][$real_name]['table'] = $specification['table'];
     foreach ($specification['columns'] as $column_name => $referenced) {
-      $sql_storage_column = _field_sql_storage_columnname($field['field_name'], $column_name);
+      $sql_storage_column = _field_sql_storage_columnname($field->id(), $column_name);
       $current['foreign keys'][$real_name]['columns'][$sql_storage_column] = $referenced;
     }
   }
 
   // Construct the revision table.
   $revision = $current;
-  $revision['description'] = "Revision archive storage for {$deleted}field {$field['id']} ({$field['field_name']})";
+  $revision['description'] = "Revision archive storage for {$deleted}field {$field->id()} ({$field->id()})";
   $revision['primary key'] = array('entity_type', 'entity_id', 'revision_id', 'deleted', 'delta', 'langcode');
   $revision['fields']['revision_id']['not null'] = TRUE;
   $revision['fields']['revision_id']['description'] = 'The entity revision id this data is attached to';
@@ -255,7 +255,7 @@ function field_sql_storage_field_storage_create_field($field) {
  */
 function field_sql_storage_field_create_field($field) {
   // Rebuild the schema now that the field has been saved.
-  if ($field['storage']['type'] == 'field_sql_storage') {
+  if ($field->storage['type'] == 'field_sql_storage') {
     drupal_get_schema(NULL, TRUE);
   }
 }
@@ -267,7 +267,7 @@ function field_sql_storage_field_create_field($field) {
  * data.
  */
 function field_sql_storage_field_update_forbid($field, $prior_field) {
-  if ($field->hasData() && $field['columns'] != $prior_field['columns']) {
+  if ($field->hasData() && $field->getSchema('columns') != $prior_field->getSchema('columns')) {
     throw new FieldUpdateForbiddenException("field_sql_storage cannot change the schema for an existing field with data.");
   }
 }
@@ -323,7 +323,7 @@ function field_sql_storage_field_storage_update_field($field, $prior_field) {
 
     foreach ($prior_schema['indexes'] as $name => $columns) {
       if (!isset($schema['indexes'][$name]) || $columns != $schema['indexes'][$name]) {
-        $real_name = _field_sql_storage_indexname($field['field_name'], $name);
+        $real_name = _field_sql_storage_indexname($field->id(), $name);
         db_drop_index($table, $real_name);
         db_drop_index($revision_table, $real_name);
       }
@@ -332,19 +332,19 @@ function field_sql_storage_field_storage_update_field($field, $prior_field) {
     $revision_table = _field_sql_storage_revision_tablename($field);
     foreach ($schema['indexes'] as $name => $columns) {
       if (!isset($prior_schema['indexes'][$name]) || $columns != $prior_schema['indexes'][$name]) {
-        $real_name = _field_sql_storage_indexname($field['field_name'], $name);
+        $real_name = _field_sql_storage_indexname($field->id(), $name);
         $real_columns = array();
         foreach ($columns as $column_name) {
           // Indexes can be specified as either a column name or an array with
           // column name and length. Allow for either case.
           if (is_array($column_name)) {
             $real_columns[] = array(
-              _field_sql_storage_columnname($field['field_name'], $column_name[0]),
+              _field_sql_storage_columnname($field->id(), $column_name[0]),
               $column_name[1],
             );
           }
           else {
-            $real_columns[] = _field_sql_storage_columnname($field['field_name'], $column_name);
+            $real_columns[] = _field_sql_storage_columnname($field->id(), $column_name);
           }
         }
         db_add_index($table, $real_name, $real_columns);
@@ -360,7 +360,7 @@ function field_sql_storage_field_storage_update_field($field, $prior_field) {
  */
 function field_sql_storage_field_storage_delete_field($field) {
   // Mark all data associated with the field for deletion.
-  $field['deleted'] = FALSE;
+  $field->deleted = FALSE;
   $table = _field_sql_storage_tablename($field);
   $revision_table = _field_sql_storage_revision_tablename($field);
   db_update($table)
@@ -368,7 +368,7 @@ function field_sql_storage_field_storage_delete_field($field) {
     ->execute();
 
   // Move the table to a unique name while the table contents are being deleted.
-  $field['deleted'] = TRUE;
+  $field->deleted = TRUE;
   $new_table = _field_sql_storage_tablename($field);
   $revision_new_table = _field_sql_storage_revision_tablename($field);
   db_rename_table($table, $new_table);
@@ -388,7 +388,7 @@ function field_sql_storage_field_storage_load($entity_type, $entities, $age, $fi
     // on each field individually is more efficient than loading all fields in
     // memory upfront with field_info_field_by_ids().
     $field = field_info_field_by_id($field_id);
-    $field_name = $field['field_name'];
+    $field_name = $field->id();
     $table = $load_current ? _field_sql_storage_tablename($field) : _field_sql_storage_revision_tablename($field);
 
     $query = db_select($table, 't')
@@ -410,11 +410,11 @@ function field_sql_storage_field_storage_load($entity_type, $entities, $age, $fi
         $delta_count[$row->entity_id][$row->langcode] = 0;
       }
 
-      if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$row->langcode] < $field['cardinality']) {
+      if ($field->cardinality == FIELD_CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$row->langcode] < $field->cardinality) {
         $item = array();
         // For each column declared by the field, populate the item
         // from the prefixed database column.
-        foreach ($field['columns'] as $column => $attributes) {
+        foreach ($field->getSchema('columns') as $column => $attributes) {
           $column_name = _field_sql_storage_columnname($field_name, $column);
           $item[$column] = $row->$column_name;
         }
@@ -441,7 +441,7 @@ function field_sql_storage_field_storage_write(EntityInterface $entity, $op, $fi
 
   foreach ($fields as $field_id) {
     $field = field_info_field_by_id($field_id);
-    $field_name = $field['field_name'];
+    $field_name = $field->id();
     $table_name = _field_sql_storage_tablename($field);
     $revision_name = _field_sql_storage_revision_tablename($field);
 
@@ -475,7 +475,7 @@ function field_sql_storage_field_storage_write(EntityInterface $entity, $op, $fi
     // Prepare the multi-insert query.
     $do_insert = FALSE;
     $columns = array('entity_type', 'entity_id', 'revision_id', 'bundle', 'delta', 'langcode');
-    foreach ($field['columns'] as $column => $attributes) {
+    foreach ($field->getSchema('columns') as $column => $attributes) {
       $columns[] = _field_sql_storage_columnname($field_name, $column);
     }
     $query = db_insert($table_name)->fields($columns);
@@ -495,7 +495,7 @@ function field_sql_storage_field_storage_write(EntityInterface $entity, $op, $fi
           'delta' => $delta,
           'langcode' => $langcode,
         );
-        foreach ($field['columns'] as $column => $attributes) {
+        foreach ($field->getSchema('columns') as $column => $attributes) {
           $record[_field_sql_storage_columnname($field_name, $column)] = isset($item[$column]) ? $item[$column] : NULL;
         }
         $query->values($record);
@@ -503,7 +503,7 @@ function field_sql_storage_field_storage_write(EntityInterface $entity, $op, $fi
           $revision_query->values($record);
         }
 
-        if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED && ++$delta_count == $field['cardinality']) {
+        if ($field->cardinality != FIELD_CARDINALITY_UNLIMITED && ++$delta_count == $field->cardinality) {
           break;
         }
       }
@@ -528,8 +528,8 @@ function field_sql_storage_field_storage_write(EntityInterface $entity, $op, $fi
  */
 function field_sql_storage_field_storage_delete(EntityInterface $entity, $fields) {
   foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) {
-    if (isset($fields[$instance['field_id']])) {
-      $field = field_info_field_by_id($instance['field_id']);
+    if (isset($fields[$instance->field_uuid])) {
+      $field = field_info_field_by_id($instance->field_uuid);
       field_sql_storage_field_storage_purge($entity, $field, $instance);
     }
   }
@@ -580,18 +580,18 @@ function field_sql_storage_field_storage_delete_revision(EntityInterface $entity
  * This function simply marks for deletion all data associated with the field.
  */
 function field_sql_storage_field_storage_delete_instance($instance) {
-  $field = field_info_field($instance['field_name']);
+  $field = field_info_field($instance->getFieldName());
   $table_name = _field_sql_storage_tablename($field);
   $revision_name = _field_sql_storage_revision_tablename($field);
   db_update($table_name)
     ->fields(array('deleted' => 1))
-    ->condition('entity_type', $instance['entity_type'])
-    ->condition('bundle', $instance['bundle'])
+    ->condition('entity_type', $instance->entity_type)
+    ->condition('bundle', $instance->bundle)
     ->execute();
   db_update($revision_name)
     ->fields(array('deleted' => 1))
-    ->condition('entity_type', $instance['entity_type'])
-    ->condition('bundle', $instance['bundle'])
+    ->condition('entity_type', $instance->entity_type)
+    ->condition('bundle', $instance->bundle)
     ->execute();
 }
 
@@ -602,8 +602,8 @@ function field_sql_storage_entity_bundle_rename($entity_type, $bundle_old, $bund
   // We need to account for deleted or inactive fields and instances.
   $instances = field_read_instances(array('entity_type' => $entity_type, 'bundle' => $bundle_new), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
   foreach ($instances as $instance) {
-    $field = field_info_field_by_id($instance['field_id']);
-    if ($field['storage']['type'] == 'field_sql_storage') {
+    $field = field_info_field_by_id($instance->field_uuid);
+    if ($field->storage['type'] == 'field_sql_storage') {
       $table_name = _field_sql_storage_tablename($field);
       $revision_name = _field_sql_storage_revision_tablename($field);
       db_update($table_name)
@@ -638,10 +638,11 @@ function field_sql_storage_field_storage_purge_field($field) {
  */
 function field_sql_storage_field_storage_details($field) {
   $details = array();
-  if (!empty($field['columns'])) {
+  $columns = $field->getSchema('columns');
+  if (!empty($columns)) {
      // Add field columns.
-    foreach ($field['columns'] as $column_name => $attributes) {
-      $real_name = _field_sql_storage_columnname($field['field_name'], $column_name);
+    foreach ($columns as $column_name => $attributes) {
+      $real_name = _field_sql_storage_columnname($field->id(), $column_name);
       $columns[$column_name] = $real_name;
     }
     return array(
diff --git a/core/modules/field_sql_storage/lib/Drupal/field_sql_storage/Entity/Tables.php b/core/modules/field_sql_storage/lib/Drupal/field_sql_storage/Entity/Tables.php
index 11aebc0..ac930f0 100644
--- a/core/modules/field_sql_storage/lib/Drupal/field_sql_storage/Entity/Tables.php
+++ b/core/modules/field_sql_storage/lib/Drupal/field_sql_storage/Entity/Tables.php
@@ -119,7 +119,8 @@ function addField($field, $type, $langcode) {
         if ($key < $count) {
           $next = $specifiers[$key + 1];
           // Is this a field column?
-          if (isset($field['columns'][$next]) || in_array($next, Field::getReservedColumns())) {
+          $schema = $field->getSchema('columns');
+          if (isset($schema[$next]) || in_array($next, Field::getReservedColumns())) {
             // Use it.
             $column = $next;
             // Do not process it again.
@@ -137,7 +138,7 @@ function addField($field, $type, $langcode) {
 
             // Get the field definitions form a mocked entity.
             $entity = entity_create($entity_type, array());
-            $propertyDefinitions = $entity->{$field['field_name']}->getPropertyDefinitions();
+            $propertyDefinitions = $entity->{$field->id()}->getPropertyDefinitions();
 
             // If the column is not yet known, ie. the
             // $node->field_image->entity case then use the id source as the
@@ -157,7 +158,7 @@ function addField($field, $type, $langcode) {
           $column = 'value';
         }
         $table = $this->ensureFieldTable($index_prefix, $field, $type, $langcode, $base_table, $entity_id_field, $field_id_field);
-        $sql_column = _field_sql_storage_columnname($field['field_name'], $column);
+        $sql_column = _field_sql_storage_columnname($field->id(), $column);
       }
       // This is an entity property (non-configurable field).
       else {
@@ -240,10 +241,10 @@ protected function ensureEntityTable($index_prefix, $property, $type, $langcode,
    * @throws \Drupal\Core\Entity\Query\QueryException
    */
   protected function ensureFieldTable($index_prefix, &$field, $type, $langcode, $base_table, $entity_id_field, $field_id_field) {
-    $field_name = $field['field_name'];
+    $field_name = $field->id();
     if (!isset($this->fieldTables[$index_prefix . $field_name])) {
       $table = $this->sqlQuery->getMetaData('age') == FIELD_LOAD_CURRENT ? _field_sql_storage_tablename($field) : _field_sql_storage_revision_tablename($field);
-      if ($field['cardinality'] != 1) {
+      if ($field->cardinality != 1) {
         $this->sqlQuery->addMetaData('simple_query', FALSE);
       }
       $entity_type = $this->sqlQuery->getMetaData('entity_type');
diff --git a/core/modules/field_sql_storage/lib/Drupal/field_sql_storage/Tests/FieldSqlStorageTest.php b/core/modules/field_sql_storage/lib/Drupal/field_sql_storage/Tests/FieldSqlStorageTest.php
index 00ebd9c..2d5ed5f 100644
--- a/core/modules/field_sql_storage/lib/Drupal/field_sql_storage/Tests/FieldSqlStorageTest.php
+++ b/core/modules/field_sql_storage/lib/Drupal/field_sql_storage/Tests/FieldSqlStorageTest.php
@@ -101,7 +101,7 @@ function testFieldAttachLoad() {
     for ($evid = 0; $evid < 4; ++$evid) {
       $values[$evid] = array();
       // Note: we insert one extra value ('<=' instead of '<').
-      for ($delta = 0; $delta <= $this->field['cardinality']; $delta++) {
+      for ($delta = 0; $delta <= $this->field->cardinality; $delta++) {
         $value = mt_rand(1, 127);
         $values[$evid][] = $value;
         $query->values(array($entity_type, $eid, $evid, $delta, $langcode, $value));
@@ -117,10 +117,10 @@ function testFieldAttachLoad() {
     $query->execute();
 
     // Load the "most current revision"
-    $entity = field_test_create_entity($eid, 0, $this->instance['bundle']);
+    $entity = field_test_create_entity($eid, 0, $this->instance->bundle);
     field_attach_load($entity_type, array($eid => $entity));
     foreach ($values[0] as $delta => $value) {
-      if ($delta < $this->field['cardinality']) {
+      if ($delta < $this->field->cardinality) {
         $this->assertEqual($entity->{$this->field_name}[$langcode][$delta]['value'], $value, "Value $delta is loaded correctly for current revision");
       }
       else {
@@ -130,10 +130,10 @@ function testFieldAttachLoad() {
 
     // Load every revision
     for ($evid = 0; $evid < 4; ++$evid) {
-      $entity = field_test_create_entity($eid, $evid, $this->instance['bundle']);
+      $entity = field_test_create_entity($eid, $evid, $this->instance->bundle);
       field_attach_load_revision($entity_type, array($eid => $entity));
       foreach ($values[$evid] as $delta => $value) {
-        if ($delta < $this->field['cardinality']) {
+        if ($delta < $this->field->cardinality) {
           $this->assertEqual($entity->{$this->field_name}[$langcode][$delta]['value'], $value, "Value $delta for revision $evid is loaded correctly");
         }
         else {
@@ -146,7 +146,7 @@ function testFieldAttachLoad() {
     // loaded.
     $eid = $evid = 1;
     $unavailable_langcode = 'xx';
-    $entity = field_test_create_entity($eid, $evid, $this->instance['bundle']);
+    $entity = field_test_create_entity($eid, $evid, $this->instance->bundle);
     $values = array($entity_type, $eid, $evid, 0, $unavailable_langcode, mt_rand(1, 127));
     db_insert($this->table)->fields($columns)->values($values)->execute();
     db_insert($this->revision_table)->fields($columns)->values($values)->execute();
@@ -160,14 +160,14 @@ function testFieldAttachLoad() {
    */
   function testFieldAttachInsertAndUpdate() {
     $entity_type = 'test_entity';
-    $entity = field_test_create_entity(0, 0, $this->instance['bundle']);
+    $entity = field_test_create_entity(0, 0, $this->instance->bundle);
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
 
     // Test insert.
     $values = array();
     // Note: we try to insert one extra value ('<=' instead of '<').
     // TODO : test empty values filtering and "compression" (store consecutive deltas).
-    for ($delta = 0; $delta <= $this->field['cardinality']; $delta++) {
+    for ($delta = 0; $delta <= $this->field->cardinality; $delta++) {
       $values[$delta]['value'] = mt_rand(1, 127);
     }
     $entity->{$this->field_name}[$langcode] = $rev_values[0] = $values;
@@ -175,7 +175,7 @@ function testFieldAttachInsertAndUpdate() {
 
     $rows = db_select($this->table, 't')->fields('t')->execute()->fetchAllAssoc('delta', PDO::FETCH_ASSOC);
     foreach ($values as $delta => $value) {
-      if ($delta < $this->field['cardinality']) {
+      if ($delta < $this->field->cardinality) {
         $this->assertEqual($rows[$delta][$this->field_name . '_value'], $value['value'], t("Value $delta is inserted correctly"));
       }
       else {
@@ -187,14 +187,14 @@ function testFieldAttachInsertAndUpdate() {
     $entity = field_test_create_entity(0, 1, $this->instance->bundle);
     $values = array();
     // Note: we try to update one extra value ('<=' instead of '<').
-    for ($delta = 0; $delta <= $this->field['cardinality']; $delta++) {
+    for ($delta = 0; $delta <= $this->field->cardinality; $delta++) {
       $values[$delta]['value'] = mt_rand(1, 127);
     }
     $entity->{$this->field_name}[$langcode] = $rev_values[1] = $values;
     field_attach_update($entity);
     $rows = db_select($this->table, 't')->fields('t')->execute()->fetchAllAssoc('delta', PDO::FETCH_ASSOC);
     foreach ($values as $delta => $value) {
-      if ($delta < $this->field['cardinality']) {
+      if ($delta < $this->field->cardinality) {
         $this->assertEqual($rows[$delta][$this->field_name . '_value'], $value['value'], t("Value $delta is updated correctly"));
       }
       else {
@@ -510,7 +510,7 @@ function testFieldSqlStorageForeignKeys() {
     $schema = $schemas[_field_sql_storage_tablename($field)];
     $this->assertEqual(count($schema['foreign keys']), 1, 'There is 1 foreign key in the schema');
     $foreign_key = reset($schema['foreign keys']);
-    $foreign_key_column = _field_sql_storage_columnname($field['field_name'], $foreign_key_name);
+    $foreign_key_column = _field_sql_storage_columnname($field->id(), $foreign_key_name);
     $this->assertEqual($foreign_key['table'], $foreign_key_name, 'Foreign key table name preserved in the schema');
     $this->assertEqual($foreign_key['columns'][$foreign_key_column], 'id', 'Foreign key column name preserved in the schema');
   }
diff --git a/core/modules/field_ui/field_ui.admin.inc b/core/modules/field_ui/field_ui.admin.inc
index 4f429cc..e8c7776 100644
--- a/core/modules/field_ui/field_ui.admin.inc
+++ b/core/modules/field_ui/field_ui.admin.inc
@@ -31,10 +31,10 @@ function field_ui_fields_list() {
 
         // Initialize the row if we encounter the field for the first time.
         if (!isset($rows[$field_name])) {
-          $rows[$field_name]['class'] = $field['locked'] ? array('menu-disabled') : array('');
-          $rows[$field_name]['data'][0] = $field['locked'] ? t('@field_name (Locked)', array('@field_name' => $field_name)) : $field_name;
-          $module_name = $field_types[$field['type']]['module'];
-          $rows[$field_name]['data'][1] = $field_types[$field['type']]['label'] . ' ' . t('(module: !module)', array('!module' => $modules[$module_name]->info['name']));
+          $rows[$field_name]['class'] = $field->locked ? array('menu-disabled') : array('');
+          $rows[$field_name]['data'][0] = $field->locked ? t('@field_name (Locked)', array('@field_name' => $field_name)) : $field_name;
+          $module_name = $field_types[$field->type]['module'];
+          $rows[$field_name]['data'][1] = $field_types[$field->type]['label'] . ' ' . t('(module: !module)', array('!module' => $modules[$module_name]->info['name']));
         }
 
         // Add the current instance.
diff --git a/core/modules/field_ui/field_ui.api.php b/core/modules/field_ui/field_ui.api.php
index b3bf03e..24a77ae 100644
--- a/core/modules/field_ui/field_ui.api.php
+++ b/core/modules/field_ui/field_ui.api.php
@@ -34,7 +34,7 @@
  *   The form definition for the field settings.
  */
 function hook_field_settings_form($field, $instance) {
-  $settings = $field['settings'];
+  $settings = $field->settings;
   $form['max_length'] = array(
     '#type' => 'number',
     '#title' => t('Maximum length'),
@@ -63,7 +63,7 @@ function hook_field_settings_form($field, $instance) {
  *   The form definition for the field instance settings.
  */
 function hook_field_instance_settings_form($field, $instance, $form_state) {
-  $settings = $instance['settings'];
+  $settings = $instance->settings;
 
   $form['text_processing'] = array(
     '#type' => 'radios',
@@ -74,7 +74,7 @@ function hook_field_instance_settings_form($field, $instance, $form_state) {
       t('Filtered text (user selects text format)'),
     ),
   );
-  if ($field['type'] == 'text_with_summary') {
+  if ($field->type == 'text_with_summary') {
     $form['display_summary'] = array(
       '#type' => 'select',
       '#title' => t('Display summary'),
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php
index bb09eab..9084189 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php
@@ -145,14 +145,14 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
         '#region_callback' => array($this, 'getRowRegion'),
         '#js_settings' => array(
           'rowHandler' => 'field',
-          'defaultFormatter' => $field_types[$field['type']]['default_formatter'],
+          'defaultFormatter' => $field_types[$field->type]['default_formatter'],
         ),
         'human_name' => array(
-          '#markup' => check_plain($instance['label']),
+          '#markup' => check_plain($instance->label()),
         ),
         'weight' => array(
           '#type' => 'textfield',
-          '#title' => t('Weight for @title', array('@title' => $instance['label'])),
+          '#title' => t('Weight for @title', array('@title' => $instance->label())),
           '#title_display' => 'invisible',
           '#default_value' => $display_options ? $display_options['weight'] : '0',
           '#size' => 3,
@@ -161,7 +161,7 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
         'parent_wrapper' => array(
           'parent' => array(
             '#type' => 'select',
-            '#title' => t('Label display for @title', array('@title' => $instance['label'])),
+            '#title' => t('Label display for @title', array('@title' => $instance->label())),
             '#title_display' => 'invisible',
             '#options' => $table['#parent_options'],
             '#empty_value' => '',
@@ -176,19 +176,19 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
         ),
         'label' => array(
           '#type' => 'select',
-          '#title' => t('Label display for @title', array('@title' => $instance['label'])),
+          '#title' => t('Label display for @title', array('@title' => $instance->label())),
           '#title_display' => 'invisible',
           '#options' => $field_label_options,
           '#default_value' => $display_options ? $display_options['label'] : 'above',
         ),
       );
 
-      $formatter_options = $this->formatterManager->getOptions($field['type']);
+      $formatter_options = $this->formatterManager->getOptions($field->type);
       $formatter_options['hidden'] = '<' . t('Hidden') . '>';
       $table[$name]['format'] = array(
         'type' => array(
           '#type' => 'select',
-          '#title' => t('Formatter for @title', array('@title' => $instance['label'])),
+          '#title' => t('Formatter for @title', array('@title' => $instance->label())),
           '#title_display' => 'invisible',
           '#options' => $formatter_options,
           '#default_value' => $display_options ? $display_options['type'] : 'hidden',
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php b/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php
index ec602ff..4bd89d0 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php
@@ -126,19 +126,19 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
 
     // Fields.
     foreach ($instances as $name => $instance) {
-      $field = field_info_field($instance['field_name']);
-      $widget_configuration = $entity_form_display->getComponent($instance['field_name']);
+      $field = field_info_field($instance->getFieldName());
+      $widget_configuration = $entity_form_display->getComponent($instance->getFieldName());
       $admin_field_path = $this->adminPath . '/fields/' . $instance->id();
       $table[$name] = array(
         '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')),
         '#row_type' => 'field',
         '#region_callback' => array($this, 'getRowRegion'),
         'label' => array(
-          '#markup' => check_plain($instance['label']),
+          '#markup' => check_plain($instance->label()),
         ),
         'weight' => array(
           '#type' => 'textfield',
-          '#title' => t('Weight for @title', array('@title' => $instance['label'])),
+          '#title' => t('Weight for @title', array('@title' => $instance->label())),
           '#title_display' => 'invisible',
           '#default_value' => $widget_configuration ? $widget_configuration['weight'] : '0',
           '#size' => 3,
@@ -147,7 +147,7 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
         'parent_wrapper' => array(
           'parent' => array(
             '#type' => 'select',
-            '#title' => t('Parent for @title', array('@title' => $instance['label'])),
+            '#title' => t('Parent for @title', array('@title' => $instance->label())),
             '#title_display' => 'invisible',
             '#options' => $table['#parent_options'],
             '#empty_value' => '',
@@ -161,11 +161,11 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
           ),
         ),
         'field_name' => array(
-          '#markup' => $instance['field_name'],
+          '#markup' => $instance->getFieldName(),
         ),
         'type' => array(
           '#type' => 'link',
-          '#title' => $field_types[$field['type']]['label'],
+          '#title' => $field_types[$field->type]['label'],
           '#href' => $admin_field_path . '/field',
           '#options' => array('attributes' => array('title' => t('Edit field settings.'))),
         ),
@@ -193,7 +193,7 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
         '#links' => $links,
       );
 
-      if (!empty($field['locked'])) {
+      if (!empty($field->locked)) {
         $table[$name]['operations'] = array('#markup' => t('Locked'));
         $table[$name]['#attributes']['class'][] = 'menu-disabled';
       }
@@ -505,7 +505,7 @@ protected function validateAddNew(array $form, array &$form_state) {
       }
       // Field name validation.
       else {
-        $field_name = $field['field_name'];
+        $field_name = $field->id();
 
         // Add the field prefix.
         $field_name = config('field_ui.settings')->get('field_prefix') . $field_name;
@@ -565,8 +565,8 @@ protected function validateAddExisting(array $form, array &$form_state) {
           form_set_error('fields][_add_existing_field][widget_type', t('Re-use existing field: you need to select a widget.'));
         }
         // Wrong widget type.
-        elseif ($field['field_name'] && ($existing_field = field_info_field($field['field_name']))) {
-          $widget_types = $this->widgetManager->getOptions($existing_field['type']);
+        elseif ($field->id() && ($existing_field = field_info_field($field->id()))) {
+          $widget_types = $this->widgetManager->getOptions($existing_field->type);
           if (!isset($widget_types[$field['widget_type']])) {
             form_set_error('fields][_add_existing_field][widget_type', t('Re-use existing field: invalid widget.'));
           }
@@ -612,7 +612,7 @@ public function submitForm(array &$form, array &$form_state) {
         'translatable' => $values['translatable'],
       );
       $instance = array(
-        'field_name' => $field['field_name'],
+        'field_name' => $field->id(),
         'entity_type' => $this->entity_type,
         'bundle' => $this->bundle,
         'label' => $values['label'],
@@ -627,7 +627,7 @@ public function submitForm(array &$form, array &$form_state) {
         // Make sure the field is displayed in the 'default' form mode (using
         // the configured widget and default settings).
         entity_get_form_display($this->entity_type, $this->bundle, 'default')
-          ->setComponent($field['field_name'], array(
+          ->setComponent($field->id(), array(
             'type' => $values['widget_type'],
             'weight' => $values['weight'],
           ))
@@ -637,7 +637,7 @@ public function submitForm(array &$form, array &$form_state) {
         // default formatter and settings). It stays hidden for other view
         // modes until it is explicitly configured.
         entity_get_display($this->entity_type, $this->bundle, 'default')
-          ->setComponent($field['field_name'])
+          ->setComponent($field->id())
           ->save();
 
         // Always show the field settings step, as the cardinality needs to be
@@ -646,10 +646,10 @@ public function submitForm(array &$form, array &$form_state) {
         $destinations[] = $this->adminPath . '/fields/' . $new_instance->id();
 
         // Store new field information for any additional submit handlers.
-        $form_state['fields_added']['_add_new_field'] = $field['field_name'];
+        $form_state['fields_added']['_add_new_field'] = $field->id();
       }
       catch (\Exception $e) {
-        drupal_set_message(t('There was a problem creating field %label: !message', array('%label' => $instance['label'], '!message' => $e->getMessage())), 'error');
+        drupal_set_message(t('There was a problem creating field %label: !message', array('%label' => $instance->label(), '!message' => $e->getMessage())), 'error');
       }
     }
 
@@ -657,12 +657,12 @@ public function submitForm(array &$form, array &$form_state) {
     if (!empty($form_values['_add_existing_field']['field_name'])) {
       $values = $form_values['_add_existing_field'];
       $field = field_info_field($values['field_name']);
-      if (!empty($field['locked'])) {
+      if (!empty($field->locked)) {
         drupal_set_message(t('The field %label cannot be added because it is locked.', array('%label' => $values['label'])), 'error');
       }
       else {
         $instance = array(
-          'field_name' => $field['field_name'],
+          'field_name' => $field->id(),
           'entity_type' => $this->entity_type,
           'bundle' => $this->bundle,
           'label' => $values['label'],
@@ -675,7 +675,7 @@ public function submitForm(array &$form, array &$form_state) {
           // Make sure the field is displayed in the 'default' form mode (using
           // the configured widget and default settings).
           entity_get_form_display($this->entity_type, $this->bundle, 'default')
-            ->setComponent($field['field_name'], array(
+            ->setComponent($field->id(), array(
               'type' => $values['widget_type'],
               'weight' => $values['weight'],
             ))
@@ -685,15 +685,15 @@ public function submitForm(array &$form, array &$form_state) {
           // default formatter and settings). It stays hidden for other view
           // modes until it is explicitly configured.
           entity_get_display($this->entity_type, $this->bundle, 'default')
-            ->setComponent($field['field_name'])
+            ->setComponent($field->id())
             ->save();
 
           $destinations[] = $this->adminPath . '/fields/' . $new_instance->id();
           // Store new field information for any additional submit handlers.
-          $form_state['fields_added']['_add_existing_field'] = $instance['field_name'];
+          $form_state['fields_added']['_add_existing_field'] = $instance->getFieldName();
         }
         catch (\Exception $e) {
-          drupal_set_message(t('There was a problem creating field instance %label: @message.', array('%label' => $instance['label'], '@message' => $e->getMessage())), 'error');
+          drupal_set_message(t('There was a problem creating field instance %label: @message.', array('%label' => $instance->label(), '@message' => $e->getMessage())), 'error');
         }
       }
     }
@@ -748,23 +748,23 @@ protected function getExistingFieldOptions() {
         // No need to look in the current bundle.
         if (!($existing_bundle == $this->bundle && $existing_entity_type == $this->entity_type)) {
           foreach ($instances as $instance) {
-            $field = field_info_field($instance['field_name']);
+            $field = field_info_field($instance->getFieldName());
             // Don't show
             // - locked fields,
             // - fields already in the current bundle,
             // - fields that cannot be added to the entity type,
             // - fields that should not be added via user interface.
 
-            if (empty($field['locked'])
-              && !field_info_instance($this->entity_type, $field['field_name'], $this->bundle)
-              && (empty($field['entity_types']) || in_array($this->entity_type, $field['entity_types']))
-              && empty($field_types[$field['type']]['no_ui'])) {
-              $widget = entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')->getComponent($instance['field_name']);
-              $info[$instance['field_name']] = array(
-                'type' => $field['type'],
-                'type_label' => $field_types[$field['type']]['label'],
-                'field' => $field['field_name'],
-                'label' => $instance['label'],
+            if (empty($field->locked)
+              && !field_info_instance($this->entity_type, $field->id(), $this->bundle)
+              && (empty($field->entity_types) || in_array($this->entity_type, $field->entity_types))
+              && empty($field_types[$field->type]['no_ui'])) {
+              $widget = entity_get_form_display($instance->entity_type, $instance->bundle, 'default')->getComponent($instance->getFieldName());
+              $info[$instance->getFieldName()] = array(
+                'type' => $field->type,
+                'type_label' => $field_types[$field->type]['label'],
+                'field' => $field->id(),
+                'label' => $instance->label(),
                 'widget_type' => $widget['type'],
               );
             }
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldEditForm.php b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldEditForm.php
index c2f0a45..32163d1 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldEditForm.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldEditForm.php
@@ -87,7 +87,7 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
     }
 
     // Build the configurable field values.
-    $cardinality = $field['cardinality'];
+    $cardinality = $field->cardinality;
     $form['field']['cardinality_container'] = array(
       // We can't use the container element because it doesn't support the title
       // or description properties.
@@ -123,10 +123,10 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
     );
 
     // Build the non-configurable field values.
-    $form['field']['field_name'] = array('#type' => 'value', '#value' => $field['field_name']);
-    $form['field']['type'] = array('#type' => 'value', '#value' => $field['type']);
-    $form['field']['module'] = array('#type' => 'value', '#value' => $field['module']);
-    $form['field']['active'] = array('#type' => 'value', '#value' => $field['active']);
+    $form['field']['field_name'] = array('#type' => 'value', '#value' => $field->id());
+    $form['field']['type'] = array('#type' => 'value', '#value' => $field->type);
+    $form['field']['module'] = array('#type' => 'value', '#value' => $field->module);
+    $form['field']['active'] = array('#type' => 'value', '#value' => $field->active);
 
     // Add settings provided by the field module. The field module is
     // responsible for not returning settings that cannot be changed if
@@ -134,7 +134,7 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
     $form['field']['settings'] = array(
       '#weight' => 10,
     );
-    $additions = \Drupal::moduleHandler()->invoke($field['module'], 'field_settings_form', array($field, $this->instance));
+    $additions = \Drupal::moduleHandler()->invoke($field->module, 'field_settings_form', array($field, $this->instance));
     if (is_array($additions)) {
       $form['field']['settings'] += $additions;
     }
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php
index 393997a..f380de2 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php
@@ -28,8 +28,8 @@ public function getFormID() {
   public function buildForm(array $form, array &$form_state, FieldInstanceInterface $field_instance = NULL) {
     parent::buildForm($form, $form_state, $field_instance);
 
-    $bundle = $this->instance['bundle'];
-    $entity_type = $this->instance['entity_type'];
+    $bundle = $this->instance->bundle;
+    $entity_type = $this->instance->entity_type;
     $field = $this->instance->getField();
     $entity_form_display = entity_get_form_display($entity_type, $bundle, 'default');
     $bundles = entity_get_bundles();
@@ -42,11 +42,11 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
     $form['#field'] = $field;
     $form['#entity_form_display'] = $entity_form_display;
     // Create an arbitrary entity object (used by the 'default value' widget).
-    $ids = (object) array('entity_type' => $this->instance['entity_type'], 'bundle' => $this->instance['bundle'], 'entity_id' => NULL);
+    $ids = (object) array('entity_type' => $this->instance->entity_type, 'bundle' => $this->instance->bundle, 'entity_id' => NULL);
     $form['#entity'] = _field_create_entity_from_ids($ids);
     $form['#entity']->field_ui_default_value = TRUE;
 
-    if (!empty($field['locked'])) {
+    if (!empty($field->locked)) {
       $form['locked'] = array(
         '#markup' => t('The field %field is locked and cannot be edited.', array('%field' => $this->instance->label())),
       );
@@ -61,7 +61,7 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
     // Build the non-configurable instance values.
     $form['instance']['field_name'] = array(
       '#type' => 'value',
-      '#value' => $this->instance['field_name'],
+      '#value' => $this->instance->getFieldName(),
     );
     $form['instance']['entity_type'] = array(
       '#type' => 'value',
@@ -76,7 +76,7 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
     $form['instance']['label'] = array(
       '#type' => 'textfield',
       '#title' => t('Label'),
-      '#default_value' => $this->instance->label() ?: $field['field_name'],
+      '#default_value' => $this->instance->label() ?: $field->id(),
       '#required' => TRUE,
       '#weight' => -20,
     );
@@ -84,7 +84,7 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
     $form['instance']['description'] = array(
       '#type' => 'textarea',
       '#title' => t('Help text'),
-      '#default_value' => !empty($this->instance['description']) ? $this->instance['description'] : '',
+      '#default_value' => !empty($this->instance->description) ? $this->instance->description : '',
       '#rows' => 5,
       '#description' => t('Instructions to present to the user below this field on the editing form.<br />Allowed HTML tags: @tags', array('@tags' => _field_filter_xss_display_allowed_tags())) . '<br />' . t('This field supports tokens.'),
       '#weight' => -10,
@@ -93,12 +93,12 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
     $form['instance']['required'] = array(
       '#type' => 'checkbox',
       '#title' => t('Required field'),
-      '#default_value' => !empty($this->instance['required']),
+      '#default_value' => !empty($this->instance->required),
       '#weight' => -5,
     );
 
     // Add additional field instance settings from the field module.
-    $additions = \Drupal::moduleHandler()->invoke($field['module'], 'field_instance_settings_form', array($field, $this->instance, $form_state));
+    $additions = \Drupal::moduleHandler()->invoke($field->module, 'field_instance_settings_form', array($field, $this->instance, $form_state));
     if (is_array($additions)) {
       $form['instance']['settings'] = $additions;
       $form['instance']['settings']['#weight'] = 10;
@@ -110,7 +110,7 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
     $form['instance']['widget']['#weight'] = 20;
 
     // Add handling for default value if not provided by any other module.
-    if (field_behaviors_widget('default_value', $this->instance) == FIELD_BEHAVIOR_DEFAULT && empty($this->instance['default_value_function'])) {
+    if (field_behaviors_widget('default_value', $this->instance) == FIELD_BEHAVIOR_DEFAULT && empty($this->instance->default_value_function)) {
       $form['instance']['default_value_widget'] = $this->getDefaultValueWidget($field, $form, $form_state);
     }
 
@@ -133,7 +133,7 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
   public function validateForm(array &$form, array &$form_state) {
     // Take the incoming values as the $this->instance definition, so that the 'default
     // value' gets validated using the instance settings being submitted.
-    $field_name = $this->instance['field_name'];
+    $field_name = $this->instance->getFieldName();
     $entity = $form['#entity'];
     $entity_form_display = $form['#entity_form_display'];
     $field = $this->instance->getField();
@@ -150,7 +150,7 @@ public function validateForm(array &$form, array &$form_state) {
 
       // Validate the value.
       $errors = array();
-      $function = $field['module'] . '_field_validate';
+      $function = $field->module . '_field_validate';
       if (function_exists($function)) {
         $function(NULL, $field, $this->instance, Language::LANGCODE_NOT_SPECIFIED, $items, $errors);
       }
@@ -182,7 +182,7 @@ public function submitForm(array &$form, array &$form_state) {
       $items = array();
       $entity_form_display->getWidget($this->instance->getField()->id)->extractFormValues($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state);
 
-      $this->instance['default_value'] = $items ? $items : NULL;
+      $this->instance->default_value = $items ? $items : NULL;
     }
 
     // Handle widget settings.
@@ -199,8 +199,8 @@ public function submitForm(array &$form, array &$form_state) {
 
     drupal_set_message(t('Saved %label configuration.', array('%label' => $this->instance->label())));
 
-    if ($this->instance['required'] && empty($this->instance['default_value']) && empty($this->instance['default_value_function']) && $this->instance['widget']['type'] == 'field_hidden') {
-      drupal_set_message(t('Field %label is required and uses the "hidden" widget. You might want to configure a default value.', array('%label' => $this->instance['label'])), 'warning');
+    if ($this->instance['required'] && empty($this->instance->default_value) && empty($this->instance->default_value_function) && $this->instance['widget']['type'] == 'field_hidden') {
+      drupal_set_message(t('Field %label is required and uses the "hidden" widget. You might want to configure a default value.', array('%label' => $this->instance->label())), 'warning');
     }
 
     $form_state['redirect'] = $this->getNextDestination();
@@ -215,7 +215,7 @@ public function delete(array &$form, array &$form_state) {
       $destination = drupal_get_destination();
       unset($_GET['destination']);
     }
-    $form_state['redirect'] = array('admin/structure/types/manage/' . $this->instance['bundle'] . '/fields/' . $this->instance->id() . '/delete', array('query' => $destination));
+    $form_state['redirect'] = array('admin/structure/types/manage/' . $this->instance->bundle . '/fields/' . $this->instance->id() . '/delete', array('query' => $destination));
   }
 
   /**
@@ -238,12 +238,12 @@ protected function getDefaultValueWidget($field, array &$form, &$form_state) {
 
     // Adjust the instance definition used for the form element. We want a
     // non-required input and no description.
-    $this->instance['required'] = FALSE;
-    $this->instance['description'] = '';
+    $this->instance->required = FALSE;
+    $this->instance->description = '';
 
     // Adjust the instance definition to use the default widget of this field type
     // instead of the hidden widget.
-    if ($this->instance['widget']['type'] == 'field_hidden') {
+    /*if ($this->instance['widget']['type'] == 'field_hidden') {
       $field_type = field_info_field_types($field['type']);
       $default_widget = $this->widgetManager->getDefinition($field_type['default_widget']);
 
@@ -252,15 +252,15 @@ protected function getDefaultValueWidget($field, array &$form, &$form_state) {
         'settings' => $default_widget['settings'],
         'weight' => 0,
       );
-    }
+    }*/
 
     // Insert the widget. Since we do not use the "official" instance definition,
     // the whole flow cannot use field_invoke_method().
     $items = array();
-    if (!empty($this->instance['default_value'])) {
-      $items = (array) $this->instance['default_value'];
+    if (!empty($this->instance->default_value)) {
+      $items = (array) $this->instance->default_value;
     }
-    $element += $entity_form_display->getWidget($this->instance->getField()->id)->form($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state);
+    $element += $entity_form_display->getWidget($this->instance->getFieldName())->form($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state);
 
     return $element;
   }
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldWidgetTypeForm.php b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldWidgetTypeForm.php
index 4f44947..f257c56 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldWidgetTypeForm.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldWidgetTypeForm.php
@@ -27,11 +27,11 @@ public function getFormID() {
   public function buildForm(array $form, array &$form_state, FieldInstanceInterface $field_instance = NULL) {
     parent::buildForm($form, $form_state, $field_instance);
 
-    drupal_set_title($this->instance['label']);
+    drupal_set_title($this->instance->label());
 
-    $bundle = $this->instance['bundle'];
-    $entity_type = $this->instance['entity_type'];
-    $field_name = $this->instance['field_name'];
+    $bundle = $this->instance->bundle;
+    $entity_type = $this->instance->entity_type;
+    $field_name = $this->instance->getFieldName();
 
     $entity_form_display = entity_get_form_display($entity_type, $bundle, 'default');
     $field = $this->instance->getField();
@@ -49,7 +49,7 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
       '#type' => 'select',
       '#title' => t('Widget type'),
       '#required' => TRUE,
-      '#options' => $this->widgetManager->getOptions($field['type']),
+      '#options' => $this->widgetManager->getOptions($field->type),
       '#default_value' => $entity_form_display->getWidget($field_name)->getPluginId(),
       '#description' => t('The type of form element you would like to present to the user when creating this field in the %type type.', array('%type' => $bundle_label)),
     );
@@ -83,14 +83,14 @@ public function submitForm(array &$form, array &$form_state) {
 
     try {
       $entity_form_display->save();
-      drupal_set_message(t('Changed the widget for field %label.', array('%label' => $instance['label'])));
+      drupal_set_message(t('Changed the widget for field %label.', array('%label' => $instance->label())));
 
-      if ($instance['required'] && empty($instance['default_value']) && empty($instance['default_value_function']) && $instance['widget']['type'] == 'field_hidden') {
-        drupal_set_message(t('Field %label is required and uses the "hidden" widget. You might want to configure a default value.', array('%label' => $instance['label'])), 'warning');
-      }
+      /*if ($instance->required && empty($instance->default_value) && empty($instance->default_value_function) && $instance['widget']['type'] == 'field_hidden') {
+        drupal_set_message(t('Field %label is required and uses the "hidden" widget. You might want to configure a default value.', array('%label' => $instance->label())), 'warning');
+      }*/
     }
     catch (\Exception $e) {
-      drupal_set_message(t('There was a problem changing the widget for field %label.', array('%label' => $instance['label'])), 'error');
+      drupal_set_message(t('There was a problem changing the widget for field %label.', array('%label' => $instance->label())), 'error');
     }
 
     $form_state['redirect'] = $this->getNextDestination();
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php
index c643cd0..d31fbb6 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php
@@ -178,10 +178,6 @@ function testNonInitializedFields() {
     );
     $this->fieldUIAddNewField('admin/structure/types/manage/' . $this->type, $edit);
 
-    // Check that no settings have been set for the 'teaser' mode.
-    $instance = field_info_instance('node', 'field_test', $this->type);
-    $this->assertFalse(isset($instance['display']['teaser']));
-
     // Check that the field appears as 'hidden' on the 'Manage display' page
     // for the 'teaser' mode.
     $this->drupalGet('admin/structure/types/manage/' . $this->type . '/display/teaser');
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php
index 471a575..3a0d0cd 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php
@@ -233,11 +233,11 @@ function assertFieldSettings($bundle, $field_name, $string = 'dummy test string'
     field_info_cache_clear();
     // Assert field settings.
     $field = field_info_field($field_name);
-    $this->assertTrue($field['settings']['test_field_setting'] == $string, 'Field settings were found.');
+    $this->assertTrue($field->settings['test_field_setting'] == $string, 'Field settings were found.');
 
     // Assert instance and widget settings.
     $instance = field_info_instance($entity_type, $field_name, $bundle);
-    $this->assertTrue($instance['settings']['test_instance_setting'] == $string, 'Field instance settings were found.');
+    $this->assertTrue($instance->settings['test_instance_setting'] == $string, 'Field instance settings were found.');
 
     // Assert widget settings.
     $widget_configuration = entity_get_form_display($entity_type, $bundle, 'default')->getComponent($field_name);
@@ -313,7 +313,7 @@ function testDefaultValue() {
     $this->assertText("Saved $field_name configuration", 'The form was successfully submitted.');
     field_info_cache_clear();
     $instance = field_info_instance('node', $field_name, $this->type);
-    $this->assertEqual($instance['default_value'], array(array('value' => 1)), 'The default value was correctly saved.');
+    $this->assertEqual($instance->default_value, array(array('value' => 1)), 'The default value was correctly saved.');
 
     // Check that the default value shows up in the form
     $this->drupalGet($admin_path);
@@ -325,10 +325,10 @@ function testDefaultValue() {
     $this->assertText("Saved $field_name configuration", 'The form was successfully submitted.');
     field_info_cache_clear();
     $instance = field_info_instance('node', $field_name, $this->type);
-    $this->assertEqual($instance['default_value'], NULL, 'The default value was correctly saved.');
+    $this->assertEqual($instance->default_value, NULL, 'The default value was correctly saved.');
 
     // Change the widget to TestFieldWidgetNoDefault.
-    entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')
+    entity_get_form_display($instance->entity_type, $instance->bundle, 'default')
       ->setComponent($field_name, array(
         'type' => 'test_field_widget_no_default',
       ))
@@ -431,13 +431,13 @@ function testHiddenFields() {
     // Create a field and an instance programmatically.
     $field_name = 'hidden_test_field';
     entity_create('field_entity', array('field_name' => $field_name, 'type' => $field_name))->save();
-    $instance = array(
+    $instance = entity_create('field_instance', array(
       'field_name' => $field_name,
       'bundle' => $this->type,
       'entity_type' => 'node',
       'label' => t('Hidden field'),
-    );
-    entity_create('field_instance', $instance)->save();
+    ))
+    $instance->save();
     entity_get_form_display('node', $this->type, 'default')
       ->setComponent($field_name)
       ->save();
@@ -446,7 +446,7 @@ function testHiddenFields() {
     // Check that the newly added instance appears on the 'Manage Fields'
     // screen.
     $this->drupalGet($bundle_path);
-    $this->assertFieldByXPath('//table[@id="field-overview"]//td[1]', $instance['label'], 'Field was created and appears in the overview page.');
+    $this->assertFieldByXPath('//table[@id="field-overview"]//td[1]', $instance->label, 'Field was created and appears in the overview page.');
 
     // Check that the instance does not appear in the 're-use existing field' row
     // on other bundles.
diff --git a/core/modules/file/file.field.inc b/core/modules/file/file.field.inc
index a46696c..1745168 100644
--- a/core/modules/file/file.field.inc
+++ b/core/modules/file/file.field.inc
@@ -38,8 +38,8 @@ function file_field_info() {
  * Implements hook_field_settings_form().
  */
 function file_field_settings_form($field, $instance) {
-  $defaults = field_info_field_settings($field['type']);
-  $settings = array_merge($defaults, $field['settings']);
+  $defaults = field_info_field_settings($field->type);
+  $settings = array_merge($defaults, $field->settings);
 
   $form['#attached']['library'][] = array('file', 'drupal.file');
 
@@ -81,7 +81,7 @@ function file_field_settings_form($field, $instance) {
  * Implements hook_field_instance_settings_form().
  */
 function file_field_instance_settings_form($field, $instance) {
-  $settings = $instance['settings'];
+  $settings = $instance->settings;
 
   $form['file_directory'] = array(
     '#type' => 'textfield',
@@ -246,8 +246,8 @@ function file_field_update(EntityInterface $entity, $field, $instance, $langcode
   // Compare the original field values with the ones that are being saved.
   $original = $entity->original->getBCEntity();
   $original_fids = array();
-  if (!empty($original->{$field['field_name']}[$langcode])) {
-    foreach ($original->{$field['field_name']}[$langcode] as $original_item) {
+  if (!empty($original->{$field->id()}[$langcode])) {
+    foreach ($original->{$field->id()}[$langcode] as $original_item) {
       $original_fids[] = $original_item['fid'];
       if (isset($original_item['fid']) && !in_array($original_item['fid'], $current_fids)) {
         // Decrement the file usage count by 1.
@@ -303,7 +303,7 @@ function file_field_is_empty($item, $field_type) {
  *   Boolean TRUE if the file will be displayed, FALSE if the file is hidden.
  */
 function file_field_displayed($item, $field) {
-  if (!empty($field['settings']['display_field'])) {
+  if (!empty($field->settings['display_field'])) {
     return (bool) $item['display'];
   }
   return TRUE;
@@ -405,8 +405,8 @@ function file_field_widget_multiple_count_validate($element, &$form_state, $form
   $field = field_info_field($element['#field_name']);
   $uploaded = count($values['fids']);
   $count = $uploaded + $current;
-  if ($count > $field['cardinality']) {
-    $keep = $uploaded - $count + $field['cardinality'];
+  if ($count > $field->cardinality) {
+    $keep = $uploaded - $count + $field->cardinality;
     $removed_files = array_slice($values['fids'], $keep);
     $removed_names = array();
     foreach ($removed_files as $fid) {
@@ -417,8 +417,8 @@ function file_field_widget_multiple_count_validate($element, &$form_state, $form
       t(
         'Field %field can only hold @max values but there were @count uploaded. The following files have been omitted as a result: %list.',
         array(
-          '%field' => $field['field_name'],
-          '@max' => $field['cardinality'],
+          '%field' => $field->id(),
+          '@max' => $field->cardinality,
           '@count' => $keep,
           '%list' => implode(', ', $removed_names),
         )
@@ -824,7 +824,7 @@ function theme_file_upload_help($variables) {
  *   fid, FALSE if it doesn't.
  */
 function file_field_find_file_reference_column($field) {
-  foreach ($field['foreign keys'] as $data) {
+  foreach ($field->getSchema('foreign keys') as $data) {
     if ($data['table'] == 'file_managed') {
       foreach ($data['columns'] as $field_column => $column) {
         if ($column == 'fid') {
diff --git a/core/modules/file/file.module b/core/modules/file/file.module
index 87b263e..82b04c2 100644
--- a/core/modules/file/file.module
+++ b/core/modules/file/file.module
@@ -1591,12 +1591,12 @@ function file_get_file_references(File $file, $field = NULL, $age = FIELD_LOAD_R
             $current_field = field_info_field($field_name);
             // If this is the first time this field type is seen, check
             // whether it references files.
-            if (!isset($field_columns[$current_field['type']])) {
-              $field_columns[$current_field['type']] = file_field_find_file_reference_column($current_field);
+            if (!isset($field_columns[$current_field->type])) {
+              $field_columns[$current_field->type] = file_field_find_file_reference_column($current_field);
             }
             // If the field type does reference files then record it.
-            if ($field_columns[$current_field['type']]) {
-              $file_fields[$entity_type][$bundle][$field_name] = $field_columns[$current_field['type']];
+            if ($field_columns[$current_field->type]) {
+              $file_fields[$entity_type][$bundle][$field_name] = $field_columns[$current_field->type];
             }
           }
         }
@@ -1627,7 +1627,7 @@ function file_get_file_references(File $file, $field = NULL, $age = FIELD_LOAD_R
   if ($field || $field_type) {
     foreach ($return as $field_name => $data) {
       $current_field = field_info_field($field_name);
-      if (($field_type && $current_field['type'] != $field_type) || ($field && $field['id'] != $current_field['id'])) {
+      if (($field_type && $current_field->type != $field_type) || ($field && $field->id() != $current_field->id)) {
         unset($return[$field_name]);
       }
     }
diff --git a/core/modules/file/file.views.inc b/core/modules/file/file.views.inc
index c9e271f..1ea90d5 100644
--- a/core/modules/file/file.views.inc
+++ b/core/modules/file/file.views.inc
@@ -455,12 +455,12 @@ function file_field_views_data($field) {
   $data = field_views_field_default_views_data($field);
   foreach ($data as $table_name => $table_data) {
     // Add the relationship only on the fid field.
-    $data[$table_name][$field['field_name'] . '_fid']['relationship'] = array(
+    $data[$table_name][$field->id() . '_fid']['relationship'] = array(
       'id' => 'standard',
       'base' => 'file_managed',
       'entity type' => 'file',
       'base field' => 'fid',
-      'label' => t('file from !field_name', array('!field_name' => $field['field_name'])),
+      'label' => t('file from !field_name', array('!field_name' => $field->id())),
     );
   }
 
@@ -473,11 +473,11 @@ function file_field_views_data($field) {
  * Views integration to provide reverse relationships on file fields.
  */
 function file_field_views_data_views_data_alter(&$data, $field) {
-  foreach ($field['bundles'] as $entity_type => $bundles) {
+  foreach ($field->getBundles() as $entity_type => $bundles) {
     $entity_info = entity_get_info($entity_type);
-    $pseudo_field_name = 'reverse_' . $field['field_name'] . '_' . $entity_type;
+    $pseudo_field_name = 'reverse_' . $field->id() . '_' . $entity_type;
 
-    list($label, $all_labels) = field_views_field_label($field['field_name']);
+    list($label, $all_labels) = field_views_field_label($field->id());
     $entity = $entity_info['label'];
     if ($entity == t('Node')) {
       $entity = t('Content');
@@ -487,12 +487,12 @@ function file_field_views_data_views_data_alter(&$data, $field) {
       'title' => t('@entity using @field', array('@entity' => $entity, '@field' => $label)),
       'help' => t('Relate each @entity with a @field set to the file.', array('@entity' => $entity, '@field' => $label)),
       'id' => 'entity_reverse',
-      'field_name' => $field['field_name'],
+      'field_name' => $field->id(),
       'field table' => _field_sql_storage_tablename($field),
-      'field field' => $field['field_name'] . '_fid',
+      'field field' => $field->id() . '_fid',
       'base' => $entity_info['base_table'],
       'base field' => $entity_info['entity_keys']['id'],
-      'label' => t('!field_name', array('!field_name' => $field['field_name'])),
+      'label' => t('!field_name', array('!field_name' => $field->id())),
       'join_extra' => array(
         0 => array(
           'field' => 'entity_type',
diff --git a/core/modules/file/lib/Drupal/file/Tests/FileFieldTestBase.php b/core/modules/file/lib/Drupal/file/Tests/FileFieldTestBase.php
index e501573..bcae614 100644
--- a/core/modules/file/lib/Drupal/file/Tests/FileFieldTestBase.php
+++ b/core/modules/file/lib/Drupal/file/Tests/FileFieldTestBase.php
@@ -73,7 +73,7 @@ function createFileField($name, $type_name, $field_settings = array(), $instance
       'settings' => array(),
       'cardinality' => !empty($field_settings['cardinality']) ? $field_settings['cardinality'] : 1,
     );
-    $field_definition['settings'] = array_merge($field_definition['settings'], $field_settings);
+    $field->settings = array_merge($field->settings, $field_settings);
     $field = entity_create('field_entity', $field_definition);
     $field->save();
 
@@ -106,7 +106,7 @@ function attachFileField($name, $entity_type, $bundle, $instance_settings = arra
       'required' => !empty($instance_settings['required']),
       'settings' => array(),
     );
-    $instance['settings'] = array_merge($instance['settings'], $instance_settings);
+    $instance->settings = array_merge($instance->settings, $instance_settings);
     entity_create('field_instance', $instance)->save();
 
     entity_get_form_display($entity_type, $bundle, 'default')
@@ -122,12 +122,12 @@ function attachFileField($name, $entity_type, $bundle, $instance_settings = arra
    */
   function updateFileField($name, $type_name, $instance_settings = array(), $widget_settings = array()) {
     $instance = field_info_instance('node', $name, $type_name);
-    $instance['settings'] = array_merge($instance['settings'], $instance_settings);
+    $instance->settings = array_merge($instance->settings, $instance_settings);
 
     $instance->save();
 
-    entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')
-      ->setComponent($instance['field_name'], array(
+    entity_get_form_display($instance->entity_type, $instance->bundle, 'default')
+      ->setComponent($instance->getFieldName(), array(
         'settings' => $widget_settings,
       ))
       ->save();
@@ -161,7 +161,7 @@ function uploadNodeFile($file, $field_name, $nid_or_type, $new_revision = TRUE,
     // Attach a file to the node.
     $field = field_info_field($field_name);
     $name = 'files[' . $field_name . '_' . $langcode . '_0]';
-    if ($field['cardinality'] != 1) {
+    if ($field->cardinality != 1) {
       $name .= '[]';
     }
     $edit[$name] = drupal_realpath($file->getFileUri());
diff --git a/core/modules/file/lib/Drupal/file/Tests/FileFieldValidateTest.php b/core/modules/file/lib/Drupal/file/Tests/FileFieldValidateTest.php
index 174ba99..7537d0a 100644
--- a/core/modules/file/lib/Drupal/file/Tests/FileFieldValidateTest.php
+++ b/core/modules/file/lib/Drupal/file/Tests/FileFieldValidateTest.php
@@ -39,7 +39,7 @@ function testRequired() {
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
     $edit = array("title" => $this->randomName());
     $this->drupalPost('node/add/' . $type_name, $edit, t('Save and publish'));
-    $this->assertRaw(t('!title field is required.', array('!title' => $instance['label'])), t('Node save failed when required file field was empty.'));
+    $this->assertRaw(t('!title field is required.', array('!title' => $instance->label())), t('Node save failed when required file field was empty.'));
 
     // Create a new node with the uploaded file.
     $nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
@@ -58,7 +58,7 @@ function testRequired() {
     // Try to post a new node without uploading a file in the multivalue field.
     $edit = array('title' => $this->randomName());
     $this->drupalPost('node/add/' . $type_name, $edit, t('Save and publish'));
-    $this->assertRaw(t('!title field is required.', array('!title' => $instance['label'])), t('Node save failed when required multiple value file field was empty.'));
+    $this->assertRaw(t('!title field is required.', array('!title' => $instance->label())), t('Node save failed when required multiple value file field was empty.'));
 
     // Create a new node with the uploaded file into the multivalue field.
     $nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
diff --git a/core/modules/file/tests/file_module_test.module b/core/modules/file/tests/file_module_test.module
index 19096f9..d0c4757 100644
--- a/core/modules/file/tests/file_module_test.module
+++ b/core/modules/file/tests/file_module_test.module
@@ -88,7 +88,7 @@ function file_module_test_form_submit($form, &$form_state) {
  * Implements hook_file_download_access().
  */
 function file_module_test_file_download_access($field, EntityInterface $entity, File $file) {
-  $instance = field_info_instance($entity->entityType(), $field['field_name'], $entity->bundle());
+  $instance = field_info_instance($entity->entityType(), $field->id(), $entity->bundle());
   // Allow the file to be downloaded only if the given arguments are correct.
   // If any are wrong, $instance will be NULL.
   if (empty($instance)) {
diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module
index 36fffda..ab97854 100644
--- a/core/modules/forum/forum.module
+++ b/core/modules/forum/forum.module
@@ -174,7 +174,7 @@ function forum_menu_local_tasks(&$data, $router_item, $root_path) {
       $links = array();
       // Loop through all bundles for forum taxonomy vocabulary field.
       $field = field_info_field('taxonomy_forums');
-      foreach ($field['bundles']['node'] as $type) {
+      foreach ($field->getBundles('node') as $type) {
         if (node_access('create', $type)) {
           $links[$type] = array(
             '#theme' => 'menu_local_action',
diff --git a/core/modules/image/image.field.inc b/core/modules/image/image.field.inc
index ab64ffe..78a180e 100644
--- a/core/modules/image/image.field.inc
+++ b/core/modules/image/image.field.inc
@@ -57,8 +57,8 @@ function image_field_info() {
  * Implements hook_field_settings_form().
  */
 function image_field_settings_form($field, $instance) {
-  $defaults = field_info_field_settings($field['type']);
-  $settings = array_merge($defaults, $field['settings']);
+  $defaults = field_info_field_settings($field->type);
+  $settings = array_merge($defaults, $field->settings);
 
   $scheme_options = array();
   foreach (file_get_stream_wrappers(STREAM_WRAPPERS_WRITE_VISIBLE) as $scheme => $stream_wrapper) {
@@ -79,7 +79,7 @@ function image_field_settings_form($field, $instance) {
     '#title' => t('Default image'),
     '#type' => 'managed_file',
     '#description' => t('If no image is uploaded, this image will be shown on display.'),
-    '#default_value' => empty($field['settings']['default_image']) ? array() : array($field['settings']['default_image']),
+    '#default_value' => empty($field->settings['default_image']) ? array() : array($field->settings['default_image']),
     '#upload_location' => $settings['uri_scheme'] . '://default_images/',
   );
 
@@ -90,7 +90,7 @@ function image_field_settings_form($field, $instance) {
  * Implements hook_field_instance_settings_form().
  */
 function image_field_instance_settings_form($field, $instance) {
-  $settings = $instance['settings'];
+  $settings = $instance->settings;
 
   // Use the file field instance settings form as a basis.
   $form = file_field_instance_settings_form($field, $instance);
@@ -198,7 +198,7 @@ function image_field_instance_settings_form($field, $instance) {
     '#type' => 'managed_file',
     '#description' => t("If no image is uploaded, this image will be shown on display and will override the field's default image."),
     '#default_value' => empty($settings['default_image']) ? array() : array($settings['default_image']),
-    '#upload_location' => $field['settings']['uri_scheme'] . '://default_images/',
+    '#upload_location' => $field->settings['uri_scheme'] . '://default_images/',
   );
 
   return $form;
@@ -233,12 +233,12 @@ function image_field_prepare_view($entity_type, $entities, $field, $instances, $
     if (empty($items[$id])) {
       $fid = array();
       // Use the default for the instance if one is available.
-      if (!empty($instances[$id]['settings']['default_image'])) {
-        $fid = array($instances[$id]['settings']['default_image']);
+      if (!empty($instances[$id]->settings['default_image'])) {
+        $fid = array($instances[$id]->settings['default_image']);
       }
       // Otherwise, use the default for the field.
-      elseif (!empty($field['settings']['default_image'])) {
-        $fid = array($field['settings']['default_image']);
+      elseif (!empty($field->settings['default_image'])) {
+        $fid = array($field->settings['default_image']);
       }
 
       // Add the default image if one is found.
diff --git a/core/modules/image/image.module b/core/modules/image/image.module
index bdcb5e9..1840744 100644
--- a/core/modules/image/image.module
+++ b/core/modules/image/image.module
@@ -350,14 +350,14 @@ function image_file_predelete(File $file) {
  * Implements hook_field_delete_field().
  */
 function image_field_delete_field($field) {
-  if ($field['type'] != 'image') {
+  if ($field->type != 'image') {
     return;
   }
 
   // The value of a managed_file element can be an array if #extended == TRUE.
-  $fid = (isset($field['settings']['default_image']['fids']) ? $field['settings']['default_image']['fids'] : $field['settings']['default_image']);
+  $fid = (isset($field->settings['default_image']['fids']) ? $field->settings['default_image']['fids'] : $field->settings['default_image']);
   if ($fid && ($file = file_load($fid[0]))) {
-    file_usage()->delete($file, 'image', 'default_image', $field['id']);
+    file_usage()->delete($file, 'image', 'default_image', $field->uuid);
   }
 }
 
@@ -370,8 +370,8 @@ function image_field_update_field($field, $prior_field) {
   }
 
   // The value of a managed_file element can be an array if #extended == TRUE.
-  $fid_new = (isset($field['settings']['default_image']['fids']) ? $field['settings']['default_image']['fids'] : $field['settings']['default_image']);
-  $fid_old = (isset($prior_field['settings']['default_image']['fids']) ? $prior_field['settings']['default_image']['fids'] : $prior_field['settings']['default_image']);
+  $fid_new = (isset($field->settings['default_image']['fids']) ? $field->settings['default_image']['fids'] : $field->settings['default_image']);
+  $fid_old = (isset($prior_field->settings['default_image']['fids']) ? $prior_field->settings['default_image']['fids'] : $prior_field->settings['default_image']);
 
   $file_new = $fid_new ? file_load($fid_new) : FALSE;
 
@@ -381,18 +381,18 @@ function image_field_update_field($field, $prior_field) {
     if ($file_new) {
       $file_new->status = FILE_STATUS_PERMANENT;
       $file_new->save();
-      file_usage()->add($file_new, 'image', 'default_image', $field['uuid']);
+      file_usage()->add($file_new, 'image', 'default_image', $field->uuid);
     }
 
     // Is there an old file?
     if ($fid_old && ($file_old = file_load($fid_old[0]))) {
-      file_usage()->delete($file_old, 'image', 'default_image', $field['uuid']);
+      file_usage()->delete($file_old, 'image', 'default_image', $field->uuid);
     }
   }
 
   // If the upload destination changed, then move the file.
-  if ($file_new && (file_uri_scheme($file_new->getFileUri()) != $field['settings']['uri_scheme'])) {
-    $directory = $field['settings']['uri_scheme'] . '://default_images/';
+  if ($file_new && (file_uri_scheme($file_new->getFileUri()) != $field->settings['uri_scheme'])) {
+    $directory = $field->settings['uri_scheme'] . '://default_images/';
     file_prepare_directory($directory, FILE_CREATE_DIRECTORY);
     file_move($file_new, $directory . $file_new->filename);
   }
@@ -403,21 +403,21 @@ function image_field_update_field($field, $prior_field) {
  */
 function image_field_delete_instance($instance) {
   // Only act on image fields.
-  $field = field_read_field($instance['field_name']);
-  if ($field['type'] != 'image') {
+  $field = field_read_field($instance->getFieldName());
+  if ($field->type != 'image') {
     return;
   }
 
   // The value of a managed_file element can be an array if the #extended
   // property is set to TRUE.
-  $fid = $instance['settings']['default_image'];
+  $fid = $instance->settings['default_image'];
   if (is_array($fid)) {
     $fid = $fid['fid'];
   }
 
   // Remove the default image when the instance is deleted.
   if ($fid && ($file = file_load($fid))) {
-    file_usage()->delete($file, 'image', 'default_image', $instance['id']);
+    file_usage()->delete($file, 'image', 'default_image', $instance->uuid);
   }
 }
 
@@ -426,18 +426,18 @@ function image_field_delete_instance($instance) {
  */
 function image_field_update_instance($instance, $prior_instance) {
   // Only act on image fields.
-  $field = field_read_field($instance['field_name']);
-  if ($field['type'] != 'image') {
+  $field = field_read_field($instance->getFieldName());
+  if ($field->type != 'image') {
     return;
   }
 
   // The value of a managed_file element can be an array if the #extended
   // property is set to TRUE.
-  $fid_new = $instance['settings']['default_image'];
+  $fid_new = $instance->settings['default_image'];
   if (isset($fid_new['fids'])) {
     $fid_new = $fid_new['fids'];
   }
-  $fid_old = $prior_instance['settings']['default_image'];
+  $fid_old = $prior_instance->settings['default_image'];
   if (isset($fid_old['fids'])) {
     $fid_old = $fid_old['fids'];
   }
@@ -449,17 +449,17 @@ function image_field_update_instance($instance, $prior_instance) {
     if ($file_new) {
       $file_new->status = FILE_STATUS_PERMANENT;
       $file_new->save();
-      file_usage()->add($file_new, 'image', 'default_image', $instance['uuid']);
+      file_usage()->add($file_new, 'image', 'default_image', $instance->uuid);
     }
     // Delete the old file, if present.
     if ($fid_old && ($file_old = file_load($fid_old[0]))) {
-      file_usage()->delete($file_old, 'image', 'default_image', $instance['uuid']);
+      file_usage()->delete($file_old, 'image', 'default_image', $instance->uuid);
     }
   }
 
   // If the upload destination changed, then move the file.
-  if ($file_new && (file_uri_scheme($file_new->getFileUri()) != $field['settings']['uri_scheme'])) {
-    $directory = $field['settings']['uri_scheme'] . '://default_images/';
+  if ($file_new && (file_uri_scheme($file_new->getFileUri()) != $field->settings['uri_scheme'])) {
+    $directory = $field->settings['uri_scheme'] . '://default_images/';
     file_prepare_directory($directory, FILE_CREATE_DIRECTORY);
     file_move($file_new, $directory . $file_new->filename);
   }
diff --git a/core/modules/image/image.views.inc b/core/modules/image/image.views.inc
index 77c4ea3..6ad2094 100644
--- a/core/modules/image/image.views.inc
+++ b/core/modules/image/image.views.inc
@@ -19,11 +19,11 @@ function image_field_views_data($field) {
   $data = field_views_field_default_views_data($field);
   foreach ($data as $table_name => $table_data) {
     // Add the relationship only on the fid field.
-    $data[$table_name][$field['field_name'] . '_fid']['relationship'] = array(
+    $data[$table_name][$field->id() . '_fid']['relationship'] = array(
       'id' => 'standard',
       'base' => 'file_managed',
       'base field' => 'fid',
-      'label' => t('image from !field_name', array('!field_name' => $field['field_name'])),
+      'label' => t('image from !field_name', array('!field_name' => $field->id())),
     );
   }
 
@@ -36,11 +36,11 @@ function image_field_views_data($field) {
  * Views integration to provide reverse relationships on image fields.
  */
 function image_field_views_data_views_data_alter(&$data, $field) {
-  foreach ($field['bundles'] as $entity_type => $bundles) {
+  foreach ($field->getBundles() as $entity_type => $bundles) {
     $entity_info = entity_get_info($entity_type);
-    $pseudo_field_name = 'reverse_' . $field['field_name'] . '_' . $entity_type;
+    $pseudo_field_name = 'reverse_' . $field->id() . '_' . $entity_type;
 
-    list($label, $all_labels) = field_views_field_label($field['field_name']);
+    list($label, $all_labels) = field_views_field_label($field->id());
     $entity = $entity_info['label'];
     if ($entity == t('Node')) {
       $entity = t('Content');
@@ -50,12 +50,12 @@ function image_field_views_data_views_data_alter(&$data, $field) {
       'title' => t('@entity using @field', array('@entity' => $entity, '@field' => $label)),
       'help' => t('Relate each @entity with a @field set to the image.', array('@entity' => $entity, '@field' => $label)),
       'id' => 'entity_reverse',
-      'field_name' => $field['field_name'],
+      'field_name' => $field->id(),
       'field table' => _field_sql_storage_tablename($field),
-      'field field' => $field['field_name'] . '_fid',
+      'field field' => $field->id() . '_fid',
       'base' => $entity_info['base_table'],
       'base field' => $entity_info['entity_keys']['id'],
-      'label' => t('!field_name', array('!field_name' => $field['field_name'])),
+      'label' => t('!field_name', array('!field_name' => $field->id())),
       'join_extra' => array(
         0 => array(
           'field' => 'entity_type',
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php
index 164cbad..4cace67 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php
@@ -62,12 +62,12 @@ function testDefaultImages() {
       'label' => $instance->label(),
       'required' => $instance->required,
       'settings' => array(
-        'default_image' => $default_images['instance2']->id(),
+        'default_image' => $default_images['instance2']->uuid,
       ),
     ));
     $instance2->save();
 
-    $widget_settings = entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')->getComponent($field['field_name']);
+    $widget_settings = entity_get_form_display($instance->entity_type, $instance->bundle, 'default')->getComponent($field->id());
     entity_get_form_display('node', 'page', 'default')
       ->setComponent($field->id(), $widget_settings)
       ->save();
@@ -142,7 +142,7 @@ function testDefaultImages() {
     );
 
     // Upload a new default for the field.
-    $field['settings']['default_image'] = array($default_images['field_new']->id());
+    $field->settings['default_image'] = array($default_images['field_new']->id());
     $field->save();
 
     // Confirm that the new default is used on the article field settings form.
@@ -177,7 +177,7 @@ function testDefaultImages() {
     );
 
     // Upload a new default for the article's field instance.
-    $instance['settings']['default_image'] = $default_images['instance_new']->id();
+    $instance->settings['default_image'] = $default_images['instance_new']->id();
     $instance->save();
 
     // Confirm the new field instance default is used on the article field
@@ -216,7 +216,7 @@ function testDefaultImages() {
     );
 
     // Remove the instance default from articles.
-    $instance['settings']['default_image'] = 0;
+    $instance->settings['default_image'] = 0;
     $instance->save();
 
     // Confirm the article field instance default has been removed.
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php
index ccc39bd..fa3593d 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php
@@ -232,7 +232,7 @@ function testImageFieldDefaultImage() {
     // Clear field info cache so the new default image is detected.
     field_info_cache_clear();
     $field = field_info_field($field_name);
-    $image = file_load($field['settings']['default_image']);
+    $image = file_load($field->settings['default_image']);
     $this->assertTrue($image->isPermanent(), 'The default image status is permanent.');
     $default_output = theme('image', array('uri' => $image->getFileUri()));
     $this->drupalGet('node/' . $node->nid);
@@ -260,7 +260,7 @@ function testImageFieldDefaultImage() {
     // Clear field info cache so the new default image is detected.
     field_info_cache_clear();
     $field = field_info_field($field_name);
-    $this->assertFalse($field['settings']['default_image'], 'Default image removed from field.');
+    $this->assertFalse($field->settings['default_image'], 'Default image removed from field.');
     // Create an image field that uses the private:// scheme and test that the
     // default image works as expected.
     $private_field_name = strtolower($this->randomName());
@@ -274,7 +274,7 @@ function testImageFieldDefaultImage() {
     field_info_cache_clear();
 
     $private_field = field_info_field($private_field_name);
-    $image = file_load($private_field['settings']['default_image']);
+    $image = file_load($private_field->settings['default_image']);
     $this->assertEqual('private', file_uri_scheme($image->getFileUri()), 'Default image uses private:// scheme.');
     $this->assertTrue($image->isPermanent(), 'The default image status is permanent.');
     // Create a new node with no image attached and ensure that default private
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php
index 3b9be9f..56fbeef 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php
@@ -69,17 +69,19 @@ function setUp() {
    *   A list of widget settings that will be added to the widget defaults.
    */
   function createImageField($name, $type_name, $field_settings = array(), $instance_settings = array(), $widget_settings = array()) {
-    $field = array(
+    $field_definition = array(
       'field_name' => $name,
       'type' => 'image',
       'settings' => array(),
       'cardinality' => !empty($field_settings['cardinality']) ? $field_settings['cardinality'] : 1,
     );
-    $field['settings'] = array_merge($field['settings'], $field_settings);
-    entity_create('field_entity', $field)->save();
+    $field_definition['settings'] = array_merge($field_definition['settings'], $field_settings);
+
+    $field = entity_create('field_entity', $field_definition);
+    $field = $field->save();
 
     $instance = array(
-      'field_name' => $field['field_name'],
+      'field_name' => $field->id(),
       'entity_type' => 'node',
       'label' => $name,
       'bundle' => $type_name,
@@ -87,19 +89,19 @@ function createImageField($name, $type_name, $field_settings = array(), $instanc
       'description' => !empty($instance_settings['description']) ? $instance_settings['description'] : '',
       'settings' => array(),
     );
-    $instance['settings'] = array_merge($instance['settings'], $instance_settings);
+    $instance->settings = array_merge($instance->settings, $instance_settings);
     $field_instance = entity_create('field_instance', $instance);
     $field_instance->save();
 
     entity_get_form_display('node', $type_name, 'default')
-      ->setComponent($field['field_name'], array(
+      ->setComponent($field->id(), array(
         'type' => 'image_image',
         'settings' => $widget_settings,
       ))
       ->save();
 
     entity_get_display('node', $type_name, 'default')
-      ->setComponent($field['field_name'])
+      ->setComponent($field->id())
       ->save();
 
     return $field_instance;
diff --git a/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php b/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php
index 2c668f2..3239545 100644
--- a/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php
+++ b/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php
@@ -465,7 +465,7 @@ function testLinkSeparateFormatter() {
         // Update the field formatter settings.
         $display_options['settings'] = array($setting => $new_value);
         entity_get_display('entity_test', 'entity_test', 'full')
-          ->setComponent($this->field['field_name'], $display_options)
+          ->setComponent($this->field->id(), $display_options)
           ->save();
 
         $this->renderTestEntity($id);
diff --git a/core/modules/link/link.module b/core/modules/link/link.module
index bfd6ebf..1efbf17 100644
--- a/core/modules/link/link.module
+++ b/core/modules/link/link.module
@@ -44,7 +44,7 @@ function link_field_instance_settings_form($field, $instance) {
   $form['title'] = array(
     '#type' => 'radios',
     '#title' => t('Allow link text'),
-    '#default_value' => isset($instance['settings']['title']) ? $instance['settings']['title'] : DRUPAL_OPTIONAL,
+    '#default_value' => isset($instance->settings['title']) ? $instance->settings['title'] : DRUPAL_OPTIONAL,
     '#options' => array(
       DRUPAL_DISABLED => t('Disabled'),
       DRUPAL_OPTIONAL => t('Optional'),
diff --git a/core/modules/node/lib/Drupal/node/Plugin/views/wizard/Node.php b/core/modules/node/lib/Drupal/node/Plugin/views/wizard/Node.php
index db8b858..8d69811 100644
--- a/core/modules/node/lib/Drupal/node/Plugin/views/wizard/Node.php
+++ b/core/modules/node/lib/Drupal/node/Plugin/views/wizard/Node.php
@@ -278,11 +278,11 @@ protected function buildFilters(&$form, &$form_state) {
     $tag_fields = array();
     foreach ($bundles as $bundle) {
       foreach (field_info_instances($this->entity_type, $bundle) as $instance) {
-        $widget = entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')->getComponent($instance['field_name']);
+        $widget = entity_get_form_display($instance->entity_type, $instance->bundle, 'default')->getComponent($instance->getFieldName());
         // We define "tag-like" taxonomy fields as ones that use the
         // "Autocomplete term widget (tagging)" widget.
         if ($widget['type'] == 'taxonomy_autocomplete') {
-          $tag_fields[] = $instance['field_name'];
+          $tag_fields[] = $instance->getFieldName();
         }
       }
     }
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTokenReplaceTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTokenReplaceTest.php
index 90b7493..4d6c50b 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeTokenReplaceTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeTokenReplaceTest.php
@@ -54,8 +54,8 @@ function testNodeTokenReplacement() {
     $tests['[node:type]'] = 'article';
     $tests['[node:type-name]'] = 'Article';
     $tests['[node:title]'] = check_plain($node->title);
-    $tests['[node:body]'] = text_sanitize($instance['settings']['text_processing'], $node->langcode, $node->body[$node->langcode][0], 'value');
-    $tests['[node:summary]'] = text_sanitize($instance['settings']['text_processing'], $node->langcode, $node->body[$node->langcode][0], 'summary');
+    $tests['[node:body]'] = text_sanitize($instance->settings['text_processing'], $node->langcode, $node->body[$node->langcode][0], 'value');
+    $tests['[node:summary]'] = text_sanitize($instance->settings['text_processing'], $node->langcode, $node->body[$node->langcode][0], 'summary');
     $tests['[node:langcode]'] = check_plain($node->langcode);
     $tests['[node:url]'] = url('node/' . $node->nid, $url_options);
     $tests['[node:edit-url]'] = url('node/' . $node->nid . '/edit', $url_options);
@@ -96,7 +96,7 @@ function testNodeTokenReplacement() {
 
     // Generate and test sanitized token - use full body as expected value.
     $tests = array();
-    $tests['[node:summary]'] = text_sanitize($instance['settings']['text_processing'], $node->langcode, $node->body[$node->langcode][0], 'value');
+    $tests['[node:summary]'] = text_sanitize($instance->settings['text_processing'], $node->langcode, $node->body[$node->langcode][0], 'value');
 
     // Test to make sure that we generated something for each token.
     $this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated for node without a summary.');
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTypeTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTypeTest.php
index 6a5b5f6..2519eeb 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeTypeTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeTypeTest.php
@@ -84,7 +84,7 @@ function testNodeTypeEditing() {
     $this->drupalLogin($web_user);
 
     $instance = field_info_instance('node', 'body', 'page');
-    $this->assertEqual($instance['label'], 'Body', 'Body field was found.');
+    $this->assertEqual($instance->label(), 'Body', 'Body field was found.');
 
     // Verify that title and body fields are displayed.
     $this->drupalGet('node/add/page');
diff --git a/core/modules/node/node.tokens.inc b/core/modules/node/node.tokens.inc
index 241b83b..48f33f1 100644
--- a/core/modules/node/node.tokens.inc
+++ b/core/modules/node/node.tokens.inc
@@ -143,11 +143,11 @@ function node_tokens($type, $tokens, array $data = array(), array $options = arr
 
             // If the summary was requested and is not empty, use it.
             if ($name == 'summary' && !empty($items[0]['summary'])) {
-              $output = $sanitize ? text_sanitize($instance['settings']['text_processing'], $field_langcode, $items[0], 'summary') : $items[0]['summary'];
+              $output = $sanitize ? text_sanitize($instance->settings['text_processing'], $field_langcode, $items[0], 'summary') : $items[0]['summary'];
             }
             // Attempt to provide a suitable version of the 'body' field.
             else {
-              $output = $sanitize ? text_sanitize($instance['settings']['text_processing'], $field_langcode, $items[0], 'value') : $items[0]['value'];
+              $output = $sanitize ? text_sanitize($instance->settings['text_processing'], $field_langcode, $items[0], 'value') : $items[0]['value'];
               // A summary was requested.
               if ($name == 'summary') {
                 // Generate an optionally trimmed summary of the body field.
@@ -163,7 +163,7 @@ function node_tokens($type, $tokens, array $data = array(), array $options = arr
                   $length = $settings['trim_length'];
                 }
 
-                $output = text_summary($output, $instance['settings']['text_processing'] ? $items[0]['format'] : NULL, $length);
+                $output = text_summary($output, $instance->settings['text_processing'] ? $items[0]['format'] : NULL, $length);
               }
             }
             $replacements[$original] = $output;
diff --git a/core/modules/number/lib/Drupal/number/Plugin/field/formatter/DefaultNumberFormatter.php b/core/modules/number/lib/Drupal/number/Plugin/field/formatter/DefaultNumberFormatter.php
index 8188dc1..7e6429c 100644
--- a/core/modules/number/lib/Drupal/number/Plugin/field/formatter/DefaultNumberFormatter.php
+++ b/core/modules/number/lib/Drupal/number/Plugin/field/formatter/DefaultNumberFormatter.php
@@ -72,8 +72,8 @@ public function viewElements(EntityInterface $entity, $langcode, array $items) {
 
       // Account for prefix and suffix.
       if ($this->getSetting('prefix_suffix')) {
-        $prefixes = isset($instance['settings']['prefix']) ? array_map('field_filter_xss', explode('|', $instance['settings']['prefix'])) : array('');
-        $suffixes = isset($instance['settings']['suffix']) ? array_map('field_filter_xss', explode('|', $instance['settings']['suffix'])) : array('');
+        $prefixes = isset($instance->settings['prefix']) ? array_map('field_filter_xss', explode('|', $instance->settings['prefix'])) : array('');
+        $suffixes = isset($instance->settings['suffix']) ? array_map('field_filter_xss', explode('|', $instance->settings['suffix'])) : array('');
         $prefix = (count($prefixes) > 1) ? format_plural($item['value'], $prefixes[0], $prefixes[1]) : $prefixes[0];
         $suffix = (count($suffixes) > 1) ? format_plural($item['value'], $suffixes[0], $suffixes[1]) : $suffixes[0];
         $output = $prefix . $output . $suffix;
diff --git a/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php b/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php
index 904509c..2def20b 100644
--- a/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php
+++ b/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php
@@ -94,7 +94,7 @@ function testNumberDecimalField() {
     // Display creation form.
     $this->drupalGet('entity_test/add');
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
-    $this->assertFieldByName("{$this->field['field_name']}[$langcode][0][value]", '', 'Widget is displayed');
+    $this->assertFieldByName("{$this->field->id()}[$langcode][0][value]", '', 'Widget is displayed');
     $this->assertRaw('placeholder="0.00"');
 
     // Submit a signed decimal value within the allowed precision and scale.
@@ -102,7 +102,7 @@ function testNumberDecimalField() {
     $edit = array(
       'user_id' => 1,
       'name' => $this->randomName(),
-      "{$this->field['field_name']}[$langcode][0][value]" => $value,
+      "{$this->field->id()}[$langcode][0][value]" => $value,
     );
     $this->drupalPost(NULL, $edit, t('Save'));
     preg_match('|entity_test/manage/(\d+)/edit|', $this->url, $match);
@@ -122,10 +122,10 @@ function testNumberDecimalField() {
     foreach ($wrong_entries as $wrong_entry) {
       $this->drupalGet('entity_test/add');
       $edit = array(
-        "{$this->field['field_name']}[$langcode][0][value]" => $wrong_entry,
+        "{$this->field->id()}[$langcode][0][value]" => $wrong_entry,
       );
       $this->drupalPost(NULL, $edit, t('Save'));
-      $this->assertRaw(t('%name must be a number.', array('%name' => $this->field['field_name'])), 'Correctly failed to save decimal value with more than one decimal point.');
+      $this->assertRaw(t('%name must be a number.', array('%name' => $this->field->id())), 'Correctly failed to save decimal value with more than one decimal point.');
     }
 
     // Try to create entries with minus sign not in the first position.
@@ -140,10 +140,10 @@ function testNumberDecimalField() {
     foreach ($wrong_entries as $wrong_entry) {
       $this->drupalGet('entity_test/add');
       $edit = array(
-        "{$this->field['field_name']}[$langcode][0][value]" => $wrong_entry,
+        "{$this->field->id()}[$langcode][0][value]" => $wrong_entry,
       );
       $this->drupalPost(NULL, $edit, t('Save'));
-      $this->assertRaw(t('%name must be a number.', array('%name' => $this->field['field_name'])), 'Correctly failed to save decimal value with minus sign in the wrong position.');
+      $this->assertRaw(t('%name must be a number.', array('%name' => $this->field->id())), 'Correctly failed to save decimal value with minus sign in the wrong position.');
     }
   }
 
diff --git a/core/modules/number/number.install b/core/modules/number/number.install
index 3c4ae7f..4520c95 100644
--- a/core/modules/number/number.install
+++ b/core/modules/number/number.install
@@ -9,7 +9,7 @@
  * Implements hook_field_schema().
  */
 function number_field_schema($field) {
-  switch ($field['type']) {
+  switch ($field->type) {
     case 'number_integer' :
       $columns = array(
         'value' => array(
@@ -32,8 +32,8 @@ function number_field_schema($field) {
       $columns = array(
         'value' => array(
           'type' => 'numeric',
-          'precision' => $field['settings']['precision'],
-          'scale' => $field['settings']['scale'],
+          'precision' => $field->settings['precision'],
+          'scale' => $field->settings['scale'],
           'not null' => FALSE
         ),
       );
diff --git a/core/modules/number/number.module b/core/modules/number/number.module
index 1504e4a..92a470d 100644
--- a/core/modules/number/number.module
+++ b/core/modules/number/number.module
@@ -60,7 +60,7 @@ function number_field_settings_form($field, $instance) {
   $settings = $field['settings'];
   $form = array();
 
-  if ($field['type'] == 'number_decimal') {
+  if ($field->type == 'number_decimal') {
     $form['precision'] = array(
       '#type' => 'select',
       '#title' => t('Precision'),
@@ -86,7 +86,7 @@ function number_field_settings_form($field, $instance) {
  * Implements hook_field_instance_settings_form().
  */
 function number_field_instance_settings_form($field, $instance) {
-  $settings = $instance['settings'];
+  $settings = $instance->settings;
 
   $form['min'] = array(
     '#type' => 'textfield',
@@ -130,16 +130,16 @@ function number_field_instance_settings_form($field, $instance) {
 function number_field_validate(EntityInterface $entity = NULL, $field, $instance, $langcode, $items, &$errors) {
   foreach ($items as $delta => $item) {
     if ($item['value'] != '') {
-      if (is_numeric($instance['settings']['min']) && $item['value'] < $instance['settings']['min']) {
-        $errors[$field['field_name']][$langcode][$delta][] = array(
+      if (is_numeric($instance->settings['min']) && $item['value'] < $instance->settings['min']) {
+        $errors[$field->id()][$langcode][$delta][] = array(
           'error' => 'number_min',
-          'message' => t('%name: the value may be no less than %min.', array('%name' => $instance['label'], '%min' => $instance['settings']['min'])),
+          'message' => t('%name: the value may be no less than %min.', array('%name' => $instance->label(), '%min' => $instance->settings['min'])),
         );
       }
-      if (is_numeric($instance['settings']['max']) && $item['value'] > $instance['settings']['max']) {
-        $errors[$field['field_name']][$langcode][$delta][] = array(
+      if (is_numeric($instance->settings['max']) && $item['value'] > $instance->settings['max']) {
+        $errors[$field->id()][$langcode][$delta][] = array(
           'error' => 'number_max',
-          'message' => t('%name: the value may be no greater than %max.', array('%name' => $instance['label'], '%max' => $instance['settings']['max'])),
+          'message' => t('%name: the value may be no greater than %max.', array('%name' => $instance->label(), '%max' => $instance->settings['max'])),
         );
       }
     }
@@ -150,12 +150,12 @@ function number_field_validate(EntityInterface $entity = NULL, $field, $instance
  * Implements hook_field_presave().
  */
 function number_field_presave(EntityInterface $entity, $field, $instance, $langcode, &$items) {
-  if ($field['type'] == 'number_decimal') {
+  if ($field->type == 'number_decimal') {
     // Let PHP round the value to ensure consistent behavior across storage
     // backends.
     foreach ($items as $delta => $item) {
       if (isset($item['value'])) {
-        $items[$delta]['value'] = round($item['value'], $field['settings']['scale']);
+        $items[$delta]['value'] = round($item['value'], $field->settings['scale']);
       }
     }
   }
diff --git a/core/modules/options/lib/Drupal/options/Tests/OptionsFieldTest.php b/core/modules/options/lib/Drupal/options/Tests/OptionsFieldTest.php
index 218e413..7125de6 100644
--- a/core/modules/options/lib/Drupal/options/Tests/OptionsFieldTest.php
+++ b/core/modules/options/lib/Drupal/options/Tests/OptionsFieldTest.php
@@ -70,7 +70,7 @@ function testUpdateAllowedValues() {
     $this->assertTrue(empty($form[$this->fieldName][$langcode][3]), 'Option 3 does not exist');
 
     // Completely new options appear.
-    $this->field['settings']['allowed_values'] = array(10 => 'Update', 20 => 'Twenty');
+    $this->field->settings['allowed_values'] = array(10 => 'Update', 20 => 'Twenty');
     $this->field->save();
     $form = \Drupal::entityManager()->getForm($entity);
     $this->assertTrue(empty($form[$this->fieldName][$langcode][1]), 'Option 1 does not exist');
diff --git a/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUITest.php b/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUITest.php
index d34f178..cee6d0f 100644
--- a/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUITest.php
+++ b/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUITest.php
@@ -232,9 +232,9 @@ function testOptionsAllowedValuesBoolean() {
     $this->assertFieldByName('on', $on, t("The 'On' value is stored correctly."));
     $this->assertFieldByName('off', $off, t("The 'Off' value is stored correctly."));
     $field = field_info_field($this->field_name);
-    $this->assertEqual($field['settings']['allowed_values'], $allowed_values, 'The allowed value is correct');
-    $this->assertFalse(isset($field['settings']['on']), 'The on value is not saved into settings');
-    $this->assertFalse(isset($field['settings']['off']), 'The off value is not saved into settings');
+    $this->assertEqual($field->settings['allowed_values'], $allowed_values, 'The allowed value is correct');
+    $this->assertFalse(isset($field->settings['on']), 'The on value is not saved into settings');
+    $this->assertFalse(isset($field->settings['off']), 'The off value is not saved into settings');
   }
 
   /**
@@ -281,7 +281,7 @@ protected function createOptionsField($type) {
    *   element.
    * @param $result
    *   Either an expected resulting array in
-   *   $field['settings']['allowed_values'], or an expected error message.
+   *   $field->settings['allowed_values'], or an expected error message.
    * @param $message
    *   Message to display.
    */
@@ -295,7 +295,7 @@ function assertAllowedValuesInput($input_string, $result, $message) {
     else {
       field_info_cache_clear();
       $field = field_info_field($this->field_name);
-      $this->assertIdentical($field['settings']['allowed_values'], $result, $message);
+      $this->assertIdentical($field->settings['allowed_values'], $result, $message);
     }
   }
 
diff --git a/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php b/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php
index 8d335c3..84fa426 100644
--- a/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php
+++ b/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php
@@ -296,7 +296,7 @@ function testSelectListSingle() {
     // Submit form: select invalid 'none' option.
     $edit = array("card_1[$langcode]" => '_none');
     $this->drupalPost(NULL, $edit, t('Save'));
-    $this->assertRaw(t('!title field is required.', array('!title' => $instance['field_name'])), 'Cannot save a required field when selecting "none" from the select list.');
+    $this->assertRaw(t('!title field is required.', array('!title' => $instance->getFieldName())), 'Cannot save a required field when selecting "none" from the select list.');
 
     // Submit form: select first option.
     $edit = array("card_1[$langcode]" => 0);
diff --git a/core/modules/options/options.install b/core/modules/options/options.install
index 6c2c8af..ae08db2 100644
--- a/core/modules/options/options.install
+++ b/core/modules/options/options.install
@@ -9,7 +9,7 @@
  * Implements hook_field_schema().
  */
 function options_field_schema($field) {
-  switch ($field['type']) {
+  switch ($field->type) {
     case 'list_text':
       $columns = array(
         'value' => array(
diff --git a/core/modules/options/options.module b/core/modules/options/options.module
index 88a2b48..57e01a8 100644
--- a/core/modules/options/options.module
+++ b/core/modules/options/options.module
@@ -71,7 +71,7 @@ function options_field_info() {
 function options_field_settings_form($field, $instance) {
   $settings = $field['settings'];
 
-  switch ($field['type']) {
+  switch ($field->type) {
     case 'list_integer':
     case 'list_float':
     case 'list_text':
@@ -83,12 +83,12 @@ function options_field_settings_form($field, $instance) {
         '#element_validate' => array('options_field_settings_form_validate_allowed_values'),
         '#field_has_data' => $field->hasData(),
         '#field' => $field,
-        '#field_type' => $field['type'],
+        '#field_type' => $field->type,
         '#access' => empty($settings['allowed_values_function']),
       );
 
       $description = '<p>' . t('The possible values this field can contain. Enter one value per line, in the format key|label.');
-      if ($field['type'] == 'list_integer' || $field['type'] == 'list_float') {
+      if ($field->type == 'list_integer' || $field->type == 'list_float') {
         $description .= '<br/>' . t('The key is the stored value, and must be numeric. The label will be used in displayed values and edit forms.');
         $description .= '<br/>' . t('The label is optional: if a line contains a single number, it will be used as key and label.');
         $description .= '<br/>' . t('Lists of labels are also accepted (one label per line), only if the field does not hold any values yet. Numeric keys will be automatically generated from the positions in the list.');
@@ -143,12 +143,12 @@ function options_field_settings_form($field, $instance) {
   }
 
   // Alter the description for allowed values depending on the widget type.
-  if ($instance['widget']['type'] == 'options_onoff') {
+  /*if ($instance['widget']['type'] == 'options_onoff') {
     $form['allowed_values']['#description'] .= '<p>' . t("For a 'single on/off checkbox' widget, define the 'off' value first, then the 'on' value in the <strong>Allowed values</strong> section. Note that the checkbox will be labeled with the label of the 'on' value.") . '</p>';
   }
   elseif ($instance['widget']['type'] == 'options_buttons') {
     $form['allowed_values']['#description'] .= '<p>' . t("The 'checkboxes/radio buttons' widget will display checkboxes if the <em>Number of values</em> option is greater than 1 for this field, otherwise radios will be displayed.") . '</p>';
-  }
+  }*/
   $form['allowed_values']['#description'] .= '<p>' . t('Allowed HTML tags in labels: @tags', array('@tags' => _field_filter_xss_display_allowed_tags())) . '</p>';
 
   $form['allowed_values_function'] = array(
@@ -168,10 +168,10 @@ function options_field_settings_form($field, $instance) {
 function options_field_settings_form_validate_allowed_values($element, &$form_state) {
   $field = $element['#field'];
   $has_data = $element['#field_has_data'];
-  $field_type = $field['type'];
+  $field_type = $field->type;
   $generate_keys = ($field_type == 'list_integer' || $field_type == 'list_float') && !$has_data;
 
-  $values = options_extract_allowed_values($element['#value'], $field['type'], $generate_keys);
+  $values = options_extract_allowed_values($element['#value'], $field->type, $generate_keys);
 
   if (!is_array($values)) {
     form_error($element, t('Allowed values list: invalid input.'));
@@ -195,7 +195,7 @@ function options_field_settings_form_validate_allowed_values($element, &$form_st
 
     // Prevent removing values currently in use.
     if ($has_data) {
-      $lost_keys = array_diff(array_keys($field['settings']['allowed_values']), array_keys($values));
+      $lost_keys = array_diff(array_keys($field->settings['allowed_values']), array_keys($values));
       if (_options_values_in_use($field, $lost_keys)) {
         form_error($element, t('Allowed values list: some values are being removed while currently in use.'));
       }
@@ -369,11 +369,11 @@ function options_allowed_values_string($values) {
  * Implements hook_field_update_forbid().
  */
 function options_field_update_forbid($field, $prior_field) {
-  if ($field['module'] == 'options' && $field->hasData()) {
+  if ($field->module == 'options' && $field->hasData()) {
     // Forbid any update that removes allowed values with actual data.
-    $lost_keys = array_diff(array_keys($prior_field['settings']['allowed_values']), array_keys($field['settings']['allowed_values']));
+    $lost_keys = array_diff(array_keys($prior_field->settings['allowed_values']), array_keys($field->settings['allowed_values']));
     if (_options_values_in_use($field, $lost_keys)) {
-      throw new FieldUpdateForbiddenException(t('A list field (@field_name) with existing data cannot have its keys changed.', array('@field_name' => $field['field_name'])));
+      throw new FieldUpdateForbiddenException(t('A list field (@field_name) with existing data cannot have its keys changed.', array('@field_name' => $field->id())));
     }
   }
 }
@@ -383,11 +383,11 @@ function options_field_update_forbid($field, $prior_field) {
  */
 function _options_values_in_use($field, $values) {
   if ($values) {
-    $field = field_info_field_by_id($field['uuid']);
+    $field = field_info_field_by_id($field->uuid);
     $factory = Drupal::service('entity.query');
-    foreach ($field['bundles'] as $entity_type => $bundle) {
+    foreach ($field->getBundles() as $entity_type => $bundle) {
       $result = $factory->get($entity_type)
-        ->condition($field['field_name'] . '.value', $values)
+        ->condition($field->id() . '.value', $values)
         ->count()
         ->accessCheck(FALSE)
         ->range(0, 1)
@@ -421,9 +421,9 @@ function options_field_validate(EntityInterface $entity = NULL, $field, $instanc
   foreach ($items as $delta => $item) {
     if (!empty($item['value'])) {
       if (!empty($allowed_values) && !isset($allowed_values[$item['value']])) {
-        $errors[$field['field_name']][$langcode][$delta][] = array(
+        $errors[$field->id()][$langcode][$delta][] = array(
           'error' => 'list_illegal_value',
-          'message' => t('%name: illegal value.', array('%name' => $instance['label'])),
+          'message' => t('%name: illegal value.', array('%name' => $instance->label())),
         );
       }
     }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityQueryRelationshipTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityQueryRelationshipTest.php
index 7a40d9b..49192ef 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityQueryRelationshipTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityQueryRelationshipTest.php
@@ -84,7 +84,7 @@ public function setUp() {
       'field_name' => $this->fieldName,
       'type' => 'taxonomy_term_reference',
     );
-    $field['settings']['allowed_values']['vocabulary'] = $vocabulary->id();
+    $field->settings['allowed_values']['vocabulary'] = $vocabulary->id();
     entity_create('field_entity', $field)->save();
     // Third, create the instance.
     entity_create('field_instance', array(
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationFormTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationFormTest.php
index 80d00b8..89363ef 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationFormTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationFormTest.php
@@ -108,7 +108,7 @@ function testEntityFormLanguage() {
     $field->translatable = TRUE;
     $field->save();
     $field = field_info_field('body');
-    $this->assertTrue($field['translatable'], 'Field body is translatable.');
+    $this->assertTrue($field->translatable, 'Field body is translatable.');
 
     // Create a body translation and check the form language.
     $langcode2 = $this->langcodes[1];
diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php
index ab3e56d..e7f6eac 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php
@@ -65,7 +65,7 @@ public function testEntityDisplayUpgrade() {
 
     // Check that the display key in the instance data was removed.
     $body_instance = field_info_instance('node', 'body', 'article');
-    $this->assertTrue(!isset($body_instance['display']));
+    $this->assertTrue(!isset($body_instance->display));
 
     // Check that the 'language' extra field is configured as expected.
     $expected = array(
@@ -193,7 +193,7 @@ function testFieldUpgradeToConfig() {
     $uuid_key = key($deleted_fields);
     $deleted_field = $deleted_fields[$uuid_key];
     $this->assertEqual($deleted_field['uuid'], $uuid_key);
-    $this->assertEqual($deleted_field['id'], 'test_deleted_field');
+    $this->assertEqual($deleted_field->id(), 'test_deleted_field');
 
     // Check that the definition of a deleted instance is stored in state rather
     // than config.
@@ -202,10 +202,10 @@ function testFieldUpgradeToConfig() {
     // Assume there was only one deleted instance in the test database.
     $uuid_key = key($deleted_instances);
     $deleted_instance = $deleted_instances[$uuid_key];
-    $this->assertEqual($deleted_instance['uuid'], $uuid_key);
-    $this->assertEqual($deleted_instance['id'], 'node.article.test_deleted_field');
+    $this->assertEqual($deleted_instance->uuid, $uuid_key);
+    $this->assertEqual($deleted_instance->id, 'node.article.test_deleted_field');
     // The deleted field uuid and deleted instance field_uuid must match.
-    $this->assertEqual($deleted_field['uuid'], $deleted_instance['field_uuid']);
+    $this->assertEqual($deleted_field['uuid'], $deleted_instance->field_uuid);
 
     // Check that pre-existing deleted field values are read correctly.
     $entity = _field_create_entity_from_ids((object) array(
diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UserPictureUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UserPictureUpgradePathTest.php
index 376f1e9..bfed9eb 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UserPictureUpgradePathTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UserPictureUpgradePathTest.php
@@ -42,8 +42,8 @@ public function testUserPictureUpgrade() {
 
     // Retrieve the field instance and check for migrated settings.
     $instance = field_info_instance('user', 'user_picture', 'user');
-    $file = entity_load('file', $instance['settings']['default_image'][0]);
-    $this->assertIdentical($instance['settings']['default_image'][0], $file->id(), 'Default user picture has been migrated.');
+    $file = entity_load('file', $instance->settings['default_image'][0]);
+    $this->assertIdentical($instance->settings['default_image'][0], $file->id(), 'Default user picture has been migrated.');
     $this->assertEqual($file->getFileUri(), 'public://user_pictures_dir/druplicon.png', 'File id matches the uri expected.');
     $this->assertEqual($file->getFilename(), 'druplicon.png');
     $this->assertEqual($file->langcode->value, Language::LANGCODE_NOT_SPECIFIED);
@@ -55,10 +55,10 @@ public function testUserPictureUpgrade() {
     $field = field_info_field('user_picture');
     $this->assertTrue(isset($usage['image']['default_image'][$field['uuid']]));
 
-    $this->assertEqual($instance['settings']['max_resolution'], '800x800', 'User picture maximum resolution has been migrated.');
-    $this->assertEqual($instance['settings']['max_filesize'], '700 KB', 'User picture maximum filesize has been migrated.');
-    $this->assertEqual($instance['description'], 'These are user picture guidelines.', 'User picture guidelines are now the user picture field description.');
-    $this->assertEqual($instance['settings']['file_directory'], 'user_pictures_dir', 'User picture directory path has been migrated.');
+    $this->assertEqual($instance->settings['max_resolution'], '800x800', 'User picture maximum resolution has been migrated.');
+    $this->assertEqual($instance->settings['max_filesize'], '700 KB', 'User picture maximum filesize has been migrated.');
+    $this->assertEqual($instance->description, 'These are user picture guidelines.', 'User picture guidelines are now the user picture field description.');
+    $this->assertEqual($instance->settings['file_directory'], 'user_pictures_dir', 'User picture directory path has been migrated.');
 
     $display_options = entity_get_display('user', 'user', 'default')->getComponent('user_picture');
     $this->assertEqual($display_options['settings']['image_style'], 'thumbnail', 'User picture image style setting has been migrated.');
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Core/Entity/Vocabulary.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Core/Entity/Vocabulary.php
index 9d55435..c5a4aff 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Core/Entity/Vocabulary.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Core/Entity/Vocabulary.php
@@ -118,8 +118,8 @@ public function postSave(EntityStorageControllerInterface $storage_controller, $
       $fields = field_read_fields();
       foreach ($fields as $field_name => $field) {
         $update_field = FALSE;
-        if ($field['type'] == 'taxonomy_term_reference') {
-          foreach ($field['settings']['allowed_values'] as $key => &$value) {
+        if ($field->type == 'taxonomy_term_reference') {
+          foreach ($field->settings['allowed_values'] as $key => &$value) {
             if ($value['vocabulary'] == $this->getOriginalID()) {
               $value['vocabulary'] = $this->id();
               $update_field = TRUE;
@@ -159,14 +159,14 @@ public static function postDelete(EntityStorageControllerInterface $storage_cont
       $modified_field = FALSE;
       // Term reference fields may reference terms from more than one
       // vocabulary.
-      foreach ($taxonomy_field['settings']['allowed_values'] as $key => $allowed_value) {
+      foreach ($taxonomy_field->settings['allowed_values'] as $key => $allowed_value) {
         if (isset($vocabularies[$allowed_value['vocabulary']])) {
-          unset($taxonomy_field['settings']['allowed_values'][$key]);
+          unset($taxonomy_field->settings['allowed_values'][$key]);
           $modified_field = TRUE;
         }
       }
       if ($modified_field) {
-        if (empty($taxonomy_field['settings']['allowed_values'])) {
+        if (empty($taxonomy_field->settings['allowed_values'])) {
           $taxonomy_field->delete();
         }
         else {
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/entity_reference/selection/TermSelection.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/entity_reference/selection/TermSelection.php
index e49f31e..bccafdc 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/entity_reference/selection/TermSelection.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/entity_reference/selection/TermSelection.php
@@ -43,7 +43,7 @@ public static function settingsForm(&$field, &$instance) {
     $form['auto_create'] = array(
       '#type' => 'checkbox',
       '#title' => t("Create referenced entities if they don't already exist"),
-      '#default_value' => $instance['settings']['handler_settings']['auto_create'],
+      '#default_value' => $instance->settings['handler_settings']['auto_create'],
     );
     return $form;
 
@@ -61,7 +61,7 @@ public function getReferencableEntities($match = NULL, $match_operator = 'CONTAI
     $options = array();
 
     $bundles = entity_get_bundles('taxonomy_term');
-    $bundle_names = !empty($this->instance['settings']['handler_settings']['target_bundles']) ? $this->instance['settings']['handler_settings']['target_bundles'] : array_keys($bundles);
+    $bundle_names = !empty($this->instance->settings['handler_settings']['target_bundles']) ? $this->instance->settings['handler_settings']['target_bundles'] : array_keys($bundles);
 
     foreach ($bundle_names as $bundle) {
       if ($vocabulary = entity_load('taxonomy_vocabulary', $bundle)) {
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php
index 1db9e15..f8e82fd 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php
@@ -171,7 +171,7 @@ function testTaxonomyTermFieldChangeMachineName() {
 
     // Check that the field instance is still attached to the vocabulary.
     $field = field_info_field($this->field_name);
-    $allowed_values = $field['settings']['allowed_values'];
+    $allowed_values = $field->settings['allowed_values'];
     $this->assertEqual($allowed_values[0]['vocabulary'], $new_name, 'Index 0: Machine name was updated correctly.');
     $this->assertEqual($allowed_values[1]['vocabulary'], $new_name, 'Index 1: Machine name was updated correctly.');
     $this->assertEqual($allowed_values[2]['vocabulary'], 'foo', 'Index 2: Machine name was left untouched.');
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php
index caf5397..11aff45 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php
@@ -55,7 +55,7 @@ function setUp() {
       ))
       ->save();
     entity_get_display('node', 'article', 'default')
-      ->setComponent($this->instance['field_name'], array(
+      ->setComponent($this->instance->getFieldName(), array(
         'type' => 'taxonomy_term_reference_link',
       ))
       ->save();
@@ -113,7 +113,7 @@ function testTaxonomyNode() {
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
     $edit["title"] = $this->randomName();
     $edit["body[$langcode][0][value]"] = $this->randomName();
-    $edit[$this->instance['field_name'] . '[' . $langcode . '][]'] = $term1->id();
+    $edit[$this->instance->getFieldName() . '[' . $langcode . '][]'] = $term1->id();
     $this->drupalPost('node/add/article', $edit, t('Save'));
 
     // Check that the term is displayed when the node is viewed.
@@ -127,7 +127,7 @@ function testTaxonomyNode() {
     $this->assertText($term1->label(), 'Term is displayed after saving the node with no changes.');
 
     // Edit the node with a different term.
-    $edit[$this->instance['field_name'] . '[' . $langcode . '][]'] = $term2->id();
+    $edit[$this->instance->getFieldName() . '[' . $langcode . '][]'] = $term2->id();
     $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
 
     $this->drupalGet('node/' . $node->nid);
@@ -146,8 +146,8 @@ function testTaxonomyNode() {
   function testNodeTermCreationAndDeletion() {
     // Enable tags in the vocabulary.
     $instance = $this->instance;
-    entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')
-      ->setComponent($instance['field_name'], array(
+    entity_get_form_display($instance->entity_type, $instance->bundle, 'default')
+      ->setComponent($instance->getFieldName(), array(
         'type' => 'taxonomy_autocomplete',
         'settings' => array(
           'placeholder' => 'Start typing here.',
@@ -167,7 +167,7 @@ function testNodeTermCreationAndDeletion() {
     $edit["body[$langcode][0][value]"] = $this->randomName();
     // Insert the terms in a comma separated list. Vocabulary 1 is a
     // free-tagging field created by the default profile.
-    $edit[$instance['field_name'] . "[$langcode]"] = drupal_implode_tags($terms);
+    $edit[$instance->getFieldName() . "[$langcode]"] = drupal_implode_tags($terms);
 
     // Verify the placeholder is there.
     $this->drupalGet('node/add/article');
@@ -515,8 +515,8 @@ function testTaxonomyGetTermByName() {
   function testReSavingTags() {
     // Enable tags in the vocabulary.
     $instance = $this->instance;
-    entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')
-      ->setComponent($instance['field_name'], array(
+    entity_get_form_display($instance->entity_type, $instance->bundle, 'default')
+      ->setComponent($instance->getFieldName(), array(
         'type' => 'taxonomy_autocomplete',
       ))
       ->save();
@@ -527,7 +527,7 @@ function testReSavingTags() {
     $edit = array();
     $edit["title"] = $this->randomName(8);
     $edit["body[$langcode][0][value]"] = $this->randomName(16);
-    $edit[$this->instance['field_name'] . '[' . $langcode . ']'] = $term->label();
+    $edit[$this->instance->getFieldName() . '[' . $langcode . ']'] = $term->label();
     $this->drupalPost('node/add/article', $edit, t('Save'));
 
     // Check that the term is displayed when editing and saving the node with no
diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module
index 980ad00..616295b 100644
--- a/core/modules/taxonomy/taxonomy.module
+++ b/core/modules/taxonomy/taxonomy.module
@@ -961,7 +961,7 @@ function taxonomy_field_validate(EntityInterface $entity = NULL, $field, $instan
       $validate = TRUE;
       if (!empty($item['tid']) && $item['tid'] != 'autocreate') {
         $validate = FALSE;
-        foreach ($field['settings']['allowed_values'] as $settings) {
+        foreach ($field->settings['allowed_values'] as $settings) {
           // If no parent is specified, check if the term is in the vocabulary.
           if (isset($settings['vocabulary']) && empty($settings['parent'])) {
             if ($settings['vocabulary'] == $terms[$item['tid']]->bundle()) {
@@ -983,9 +983,9 @@ function taxonomy_field_validate(EntityInterface $entity = NULL, $field, $instan
         }
       }
       if (!$validate) {
-        $errors[$field['field_name']][$langcode][$delta][] = array(
+        $errors[$field->id()][$langcode][$delta][] = array(
           'error' => 'taxonomy_term_reference_illegal_value',
-          'message' => t('%name: illegal value.', array('%name' => $instance['label'])),
+          'message' => t('%name: illegal value.', array('%name' => $instance->label())),
         );
       }
     }
@@ -1064,7 +1064,7 @@ function taxonomy_field_settings_form($field, $instance) {
     '#tree' => TRUE,
   );
 
-  foreach ($field['settings']['allowed_values'] as $delta => $tree) {
+  foreach ($field->settings['allowed_values'] as $delta => $tree) {
     $form['allowed_values'][$delta]['vocabulary'] = array(
       '#type' => 'select',
       '#title' => t('Vocabulary'),
@@ -1199,9 +1199,9 @@ function taxonomy_build_node_index($node) {
     // Collect a unique list of all the term IDs from all node fields.
     $tid_all = array();
     foreach (field_info_instances('node', $node->type) as $instance) {
-      $field_name = $instance['field_name'];
+      $field_name = $instance->getFieldName();
       $field = field_info_field($field_name);
-      if ($field['module'] == 'taxonomy' && $field['storage']['type'] == 'field_sql_storage') {
+      if ($field->module == 'taxonomy' && $field->storage['type'] == 'field_sql_storage') {
         // If a field value is not set in the node object when $node->save() is
         // called, the old value from $node->original is used.
         if (isset($node->{$field_name})) {
diff --git a/core/modules/taxonomy/taxonomy.pages.inc b/core/modules/taxonomy/taxonomy.pages.inc
index d70b8fd..593c620 100644
--- a/core/modules/taxonomy/taxonomy.pages.inc
+++ b/core/modules/taxonomy/taxonomy.pages.inc
@@ -110,7 +110,7 @@ function taxonomy_autocomplete($field_name) {
   $tags_typed = Drupal::request()->query->get('q');
 
   // Make sure the field exists and is a taxonomy field.
-  if (!($field = field_info_field($field_name)) || $field['type'] !== 'taxonomy_term_reference') {
+  if (!($field = field_info_field($field_name)) || $field->type !== 'taxonomy_term_reference') {
     // Error string. The JavaScript handler will realize this is not JSON and
     // will display it as debugging information.
     print t('Taxonomy field @field_name not found.', array('@field_name' => $field_name));
@@ -126,7 +126,7 @@ function taxonomy_autocomplete($field_name) {
 
     // Part of the criteria for the query come from the field's own settings.
     $vids = array();
-    foreach ($field['settings']['allowed_values'] as $tree) {
+    foreach ($field->settings['allowed_values'] as $tree) {
       $vids[] = $tree['vocabulary'];
     }
 
diff --git a/core/modules/taxonomy/taxonomy.views.inc b/core/modules/taxonomy/taxonomy.views.inc
index d52819b..faa5087 100644
--- a/core/modules/taxonomy/taxonomy.views.inc
+++ b/core/modules/taxonomy/taxonomy.views.inc
@@ -341,16 +341,16 @@ function taxonomy_field_views_data($field) {
     foreach ($table_data as $field_name => $field_data) {
       if (isset($field_data['filter']) && $field_name != 'delta') {
         $data[$table_name][$field_name]['filter']['id'] = 'taxonomy_index_tid';
-        $data[$table_name][$field_name]['filter']['vocabulary'] = $field['settings']['allowed_values'][0]['vocabulary'];
+        $data[$table_name][$field_name]['filter']['vocabulary'] = $field->settings['allowed_values'][0]['vocabulary'];
       }
     }
 
     // Add the relationship only on the tid field.
-    $data[$table_name][$field['field_name'] . '_tid']['relationship'] = array(
+    $data[$table_name][$field->id() . '_tid']['relationship'] = array(
       'id' => 'standard',
       'base' => 'taxonomy_term_data',
       'base field' => 'tid',
-      'label' => t('term from !field_name', array('!field_name' => $field['field_name'])),
+      'label' => t('term from !field_name', array('!field_name' => $field->id())),
     );
 
   }
@@ -364,11 +364,11 @@ function taxonomy_field_views_data($field) {
  * Views integration to provide reverse relationships on term references.
  */
 function taxonomy_field_views_data_views_data_alter(&$data, $field) {
-  foreach ($field['bundles'] as $entity_type => $bundles) {
+  foreach ($field->getBundles() as $entity_type => $bundles) {
     $entity_info = entity_get_info($entity_type);
-    $pseudo_field_name = 'reverse_' . $field['field_name'] . '_' . $entity_type;
+    $pseudo_field_name = 'reverse_' . $field->id() . '_' . $entity_type;
 
-    list($label, $all_labels) = field_views_field_label($field['field_name']);
+    list($label, $all_labels) = field_views_field_label($field->id());
     $entity = $entity_info['label'];
     if ($entity == t('Node')) {
       $entity = t('Content');
@@ -378,12 +378,12 @@ function taxonomy_field_views_data_views_data_alter(&$data, $field) {
       'title' => t('@entity using @field', array('@entity' => $entity, '@field' => $label)),
       'help' => t('Relate each @entity with a @field set to the term.', array('@entity' => $entity, '@field' => $label)),
       'id' => 'entity_reverse',
-      'field_name' => $field['field_name'],
+      'field_name' => $field->id(),
       'field table' => _field_sql_storage_tablename($field),
-      'field field' => $field['field_name'] . '_tid',
+      'field field' => $field->id() . '_tid',
       'base' => $entity_info['base_table'],
       'base field' => $entity_info['entity_keys']['id'],
-      'label' => t('!field_name', array('!field_name' => $field['field_name'])),
+      'label' => t('!field_name', array('!field_name' => $field->id())),
       'join_extra' => array(
         0 => array(
           'field' => 'entity_type',
diff --git a/core/modules/text/lib/Drupal/text/TextProcessed.php b/core/modules/text/lib/Drupal/text/TextProcessed.php
index 6e8cb83..ed307bf 100644
--- a/core/modules/text/lib/Drupal/text/TextProcessed.php
+++ b/core/modules/text/lib/Drupal/text/TextProcessed.php
@@ -69,7 +69,7 @@ public function getValue($langcode = NULL) {
     $entity = $field->getParent();
     $instance = field_info_instance($entity->entityType(), $field->getName(), $entity->bundle());
 
-    if (!empty($instance['settings']['text_processing']) && $this->format->getValue()) {
+    if (!empty($instance->settings['text_processing']) && $this->format->getValue()) {
       return check_markup($this->text->getValue(), $this->format->getValue(), $entity->language()->langcode);
     }
     else {
diff --git a/core/modules/text/text.install b/core/modules/text/text.install
index 72d879f..d87d7f7 100644
--- a/core/modules/text/text.install
+++ b/core/modules/text/text.install
@@ -9,12 +9,12 @@
  * Implements hook_field_schema().
  */
 function text_field_schema($field) {
-  switch ($field['type']) {
+  switch ($field->type) {
     case 'text':
       $columns = array(
         'value' => array(
           'type' => 'varchar',
-          'length' => $field['settings']['max_length'],
+          'length' => $field->settings['max_length'],
           'not null' => FALSE,
         ),
       );
diff --git a/core/modules/text/text.module b/core/modules/text/text.module
index 4bc0f30..205a524 100644
--- a/core/modules/text/text.module
+++ b/core/modules/text/text.module
@@ -85,11 +85,11 @@ function text_field_info() {
  * Implements hook_field_settings_form().
  */
 function text_field_settings_form($field, $instance) {
-  $settings = $field['settings'];
+  $settings = $field->settings;
 
   $form = array();
 
-  if ($field['type'] == 'text') {
+  if ($field->type == 'text') {
     $form['max_length'] = array(
       '#type' => 'number',
       '#title' => t('Maximum length'),
@@ -110,7 +110,7 @@ function text_field_settings_form($field, $instance) {
  * Implements hook_field_instance_settings_form().
  */
 function text_field_instance_settings_form($field, $instance) {
-  $settings = $instance['settings'];
+  $settings = $instance->settings;
 
   $form['text_processing'] = array(
     '#type' => 'radios',
@@ -121,7 +121,7 @@ function text_field_instance_settings_form($field, $instance) {
       t('Filtered text (user selects text format)'),
     ),
   );
-  if ($field['type'] == 'text_with_summary') {
+  if ($field->type == 'text_with_summary') {
     $form['display_summary'] = array(
       '#type' => 'checkbox',
       '#title' => t('Summary input'),
@@ -146,17 +146,17 @@ function text_field_validate(EntityInterface $entity = NULL, $field, $instance,
     //   length can be exceeded very easily.
     foreach (array('value', 'summary') as $column) {
       if (!empty($item[$column])) {
-        if (!empty($field['settings']['max_length']) && drupal_strlen($item[$column]) > $field['settings']['max_length']) {
+        if (!empty($field->settings['max_length']) && drupal_strlen($item[$column]) > $field->settings['max_length']) {
           switch ($column) {
             case 'value':
-              $message = t('%name: the text may not be longer than %max characters.', array('%name' => $instance['label'], '%max' => $field['settings']['max_length']));
+              $message = t('%name: the text may not be longer than %max characters.', array('%name' => $instance->label(), '%max' => $field->settings['max_length']));
               break;
 
             case 'summary':
-              $message = t('%name: the summary may not be longer than %max characters.', array('%name' => $instance['label'], '%max' => $field['settings']['max_length']));
+              $message = t('%name: the summary may not be longer than %max characters.', array('%name' => $instance->label(), '%max' => $field->settings['max_length']));
               break;
           }
-          $errors[$field['field_name']][$langcode][$delta][] = array(
+          $errors[$field->id()][$langcode][$delta][] = array(
             'error' => "text_{$column}_length",
             'message' => $message,
           );
@@ -178,10 +178,10 @@ function text_field_load($entity_type, $entities, $field, $instances, $langcode,
     foreach ($items[$id] as $delta => $item) {
       // Only process items with a cacheable format, the rest will be handled
       // by formatters if needed.
-      if (empty($instances[$id]['settings']['text_processing']) || filter_format_allowcache($item['format'])) {
-        $items[$id][$delta]['safe_value'] = isset($item['value']) ? text_sanitize($instances[$id]['settings']['text_processing'], $langcode, $item, 'value') : '';
-        if ($field['type'] == 'text_with_summary') {
-          $items[$id][$delta]['safe_summary'] = isset($item['summary']) ? text_sanitize($instances[$id]['settings']['text_processing'], $langcode, $item, 'summary') : '';
+      if (empty($instances[$id]->settings['text_processing']) || filter_format_allowcache($item['format'])) {
+        $items[$id][$delta]['safe_value'] = isset($item['value']) ? text_sanitize($instances[$id]->settings['text_processing'], $langcode, $item, 'value') : '';
+        if ($field->type == 'text_with_summary') {
+          $items[$id][$delta]['safe_summary'] = isset($item['summary']) ? text_sanitize($instances[$id]->settings['text_processing'], $langcode, $item, 'summary') : '';
         }
       }
     }
@@ -365,7 +365,7 @@ function text_summary($text, $format = NULL, $size = NULL) {
 function text_field_prepare_translation(EntityInterface $entity, $field, $instance, $langcode, &$items, EntityInterface $source_entity, $source_langcode) {
   // If the translating user is not permitted to use the assigned text format,
   // we must not expose the source values.
-  $field_name = $field['field_name'];
+  $field_name = $field->id();
   if (!empty($source_entity->{$field_name}[$source_langcode])) {
     $formats = filter_formats();
     foreach ($source_entity->{$field_name}[$source_langcode] as $delta => $item) {
diff --git a/core/modules/translation_entity/lib/Drupal/translation_entity/EntityTranslationController.php b/core/modules/translation_entity/lib/Drupal/translation_entity/EntityTranslationController.php
index 906248a..fba7d3f 100644
--- a/core/modules/translation_entity/lib/Drupal/translation_entity/EntityTranslationController.php
+++ b/core/modules/translation_entity/lib/Drupal/translation_entity/EntityTranslationController.php
@@ -50,9 +50,9 @@ public function removeTranslation(EntityInterface $entity, $langcode) {
     // @todo Handle properties.
     // Remove field translations.
     foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) {
-      $field_name = $instance['field_name'];
+      $field_name = $instance->getFieldName();
       $field = field_info_field($field_name);
-      if ($field['translatable']) {
+      if ($field->translatable) {
         $entity->{$field_name}[$langcode] = array();
       }
     }
diff --git a/core/modules/translation_entity/lib/Drupal/translation_entity/FieldTranslationSynchronizer.php b/core/modules/translation_entity/lib/Drupal/translation_entity/FieldTranslationSynchronizer.php
index 39d1a21..8d2016b 100644
--- a/core/modules/translation_entity/lib/Drupal/translation_entity/FieldTranslationSynchronizer.php
+++ b/core/modules/translation_entity/lib/Drupal/translation_entity/FieldTranslationSynchronizer.php
@@ -66,14 +66,14 @@ public function synchronizeFields(EntityInterface $entity, $sync_langcode, $orig
 
       // Sync when the field is not empty, when the synchronization translations
       // setting is set, and the field is translatable.
-      if (!$entity->get($field_name)->isEmpty() && !empty($instance['settings']['translation_sync']) && field_is_translatable($entity_type, $field)) {
+      if (!$entity->get($field_name)->isEmpty() && !empty($instance->settings['translation_sync']) && field_is_translatable($entity_type, $field)) {
         // Retrieve all the untranslatable column groups and merge them into
         // single list.
-        $groups = array_keys(array_diff($instance['settings']['translation_sync'], array_filter($instance['settings']['translation_sync'])));
+        $groups = array_keys(array_diff($instance->settings['translation_sync'], array_filter($instance->settings['translation_sync'])));
         if (!empty($groups)) {
           $columns = array();
           foreach ($groups as $group) {
-            $info = $field['settings']['column_groups'][$group];
+            $info = $field->settings['column_groups'][$group];
             // A missing 'columns' key indicates we have a single-column group.
             $columns = array_merge($columns, isset($info['columns']) ? $info['columns'] : array($group));
           }
diff --git a/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationSettingsTest.php b/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationSettingsTest.php
index cb90b6d..83b4b37 100644
--- a/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationSettingsTest.php
+++ b/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationSettingsTest.php
@@ -90,7 +90,7 @@ function testSettingsUI() {
     $this->assertSettings('comment', 'comment_node_article', TRUE, $edit);
     field_info_cache_clear();
     $field = field_info_field('comment_body');
-    $this->assertTrue($field['translatable'], 'Comment body is translatable.');
+    $this->assertTrue($field->translatable, 'Comment body is translatable.');
 
     // Test that language settings are correctly stored.
     $language_configuration = language_get_default_configuration('comment', 'comment_node_article');
diff --git a/core/modules/translation_entity/translation_entity.admin.inc b/core/modules/translation_entity/translation_entity.admin.inc
index 01e9368..bb342bd 100644
--- a/core/modules/translation_entity/translation_entity.admin.inc
+++ b/core/modules/translation_entity/translation_entity.admin.inc
@@ -24,11 +24,11 @@
 function translation_entity_field_sync_widget(Field $field, FieldInstance $instance) {
   $element = array();
 
-  if (!empty($field['settings']['column_groups']) && count($field['settings']['column_groups']) > 1) {
+  if (!empty($field->settings['column_groups']) && count($field->settings['column_groups']) > 1) {
     $options = array();
     $default = array();
 
-    foreach ($field['settings']['column_groups'] as $group => $info) {
+    foreach ($field->settings['column_groups'] as $group => $info) {
       $options[$group] = $info['label'];
       $default[$group] = !empty($info['translatable']) ? $group : FALSE;
     }
@@ -39,7 +39,7 @@ function translation_entity_field_sync_widget(Field $field, FieldInstance $insta
       '#type' => 'checkboxes',
       '#title' => t('Translatable elements'),
       '#options' => $options,
-      '#default_value' => !empty($instance['settings']['translation_sync']) ? $instance['settings']['translation_sync'] : $default,
+      '#default_value' => !empty($instance->settings['translation_sync']) ? $instance->settings['translation_sync'] : $default,
       '#attached' => array(
         'library' => array(
           array('translation_entity', 'drupal.translation_entity.admin'),
@@ -97,9 +97,9 @@ function _translation_entity_form_language_content_settings_form_alter(array &$f
           foreach ($fields as $field_name => $instance) {
             $field = field_info_field($field_name);
             $form['settings'][$entity_type][$bundle]['fields'][$field_name] = array(
-              '#label' => $instance['label'],
+              '#label' => $instance->label(),
               '#type' => 'checkbox',
-              '#default_value' => $field['translatable'],
+              '#default_value' => $field->translatable,
             );
             $column_element = translation_entity_field_sync_widget($field, $instance);
             if ($column_element) {
@@ -337,7 +337,7 @@ function _translation_entity_update_field_translatability($settings) {
   $operations = array();
   foreach ($fields as $field_name => $translatable) {
     $field = field_info_field($field_name);
-    if ($field['translatable'] != $translatable) {
+    if ($field->translatable != $translatable) {
       // If a field is untranslatable, it can have no data except under
       // Language::LANGCODE_NOT_SPECIFIED. Thus we need a field to be translatable before
       // we convert data to the entity language. Conversely we need to switch
@@ -374,7 +374,7 @@ function translation_entity_translatable_form(array $form, array &$form_state, $
   $t_args = array('%name' => $field_name);
 
   $warning = t('By submitting this form these changes will apply to the %name field everywhere it is used.', $t_args);
-  if ($field['translatable']) {
+  if ($field->translatable) {
     $title = t('Are you sure you want to disable translation for the %name field?', $t_args);
     $warning .= "<br>" . t("<strong>All the existing translations of this field will be deleted.</strong><br>This action cannot be undone.");
   }
@@ -389,7 +389,7 @@ function translation_entity_translatable_form(array $form, array &$form_state, $
   // submits from toggling translatability.
   $form['translatable'] = array(
     '#type' => 'hidden',
-    '#default_value' => $field['translatable'],
+    '#default_value' => $field->translatable,
   );
 
   return confirm_form($form, $title, '', $warning);
@@ -413,7 +413,7 @@ function translation_entity_translatable_form_submit(array $form, array $form_st
   $field_name = $form_state['field']['field_name'];
   $field = field_info_field($field_name);
 
-  if ($field['translatable'] !== $translatable) {
+  if ($field->translatable !== $translatable) {
     // Field translatability has changed since form creation, abort.
     $t_args = array('%field_name');
     $msg = $translatable ?
@@ -460,8 +460,8 @@ function translation_entity_translatable_form_submit(array $form, array $form_st
  */
 function translation_entity_translatable_switch($translatable, $field_name) {
   $field = field_info_field($field_name);
-  if ($field['translatable'] !== $translatable) {
-    $field['translatable'] = $translatable;
+  if ($field->translatable !== $translatable) {
+    $field->translatable = $translatable;
     $field->save();
   }
 }
@@ -477,7 +477,8 @@ function translation_entity_translatable_switch($translatable, $field_name) {
  */
 function translation_entity_translatable_batch($translatable, $field_name, &$context) {
   $field = field_info_field($field_name);
-  $column = isset($field['columns']['value']) ? 'value' : key($field['columns']);
+  $columns = $field->getSchema('columns');
+  $column = isset($columns['value']) ? 'value' : key($columns);
   $query_field = "$field_name.$column";
 
   // Determine the entity types to act on.
diff --git a/core/modules/translation_entity/translation_entity.module b/core/modules/translation_entity/translation_entity.module
index dec0460..5f97c47 100644
--- a/core/modules/translation_entity/translation_entity.module
+++ b/core/modules/translation_entity/translation_entity.module
@@ -622,9 +622,9 @@ function translation_entity_form_alter(array &$form, array &$form_state) {
       }
       else {
         foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) {
-          $field_name = $instance['field_name'];
+          $field_name = $instance->getFieldName();
           $field = field_info_field($field_name);
-          $form[$field_name]['#multilingual'] = !empty($field['translatable']);
+          $form[$field_name]['#multilingual'] = !empty($field->translatable);
         }
       }
     }
@@ -657,9 +657,9 @@ function translation_entity_field_language_alter(&$display_language, $context) {
           //   entity language and with Language::LANGCODE_DEFAULT. We need need to unset
           //   both until we remove the BC layer.
           if ($langcode == $entity_langcode) {
-            unset($entity->{$instance['field_name']}[Language::LANGCODE_DEFAULT]);
+            unset($entity->{$instance->getFieldName()}[Language::LANGCODE_DEFAULT]);
           }
-          unset($entity->{$instance['field_name']}[$langcode]);
+          unset($entity->{$instance->getFieldName()}[$langcode]);
         }
       }
     }
@@ -806,8 +806,8 @@ function translation_entity_field_extra_fields() {
  */
 function translation_entity_form_field_ui_field_edit_form_alter(array &$form, array &$form_state, $form_id) {
   $field = $form['#field'];
-  $field_name = $field['field_name'];
-  $translatable = $field['translatable'];
+  $field_name = $field->id();
+  $translatable = $field->translatable;
   $label = t('Field translation');
 
   if ($field->hasData()) {
@@ -1020,13 +1020,13 @@ function translation_entity_save_settings($settings) {
           foreach ($bundle_settings['columns'] as $field_name => $column_settings) {
             $field = field_info_field($field_name);
             $instance = field_info_instance($entity_type, $field_name, $bundle);
-            if ($field['translatable']) {
-              $instance['settings']['translation_sync'] = $column_settings;
+            if ($field->translatable) {
+              $instance->settings['translation_sync'] = $column_settings;
             }
             // If the field does not have translatable enabled we need to reset
             // the sync settings to their defaults.
             else {
-              unset($instance['settings']['translation_sync']);
+              unset($instance->settings['translation_sync']);
             }
             $instance->save();
           }
diff --git a/core/modules/translation_entity/translation_entity.pages.inc b/core/modules/translation_entity/translation_entity.pages.inc
index cd212eb..0586b20 100644
--- a/core/modules/translation_entity/translation_entity.pages.inc
+++ b/core/modules/translation_entity/translation_entity.pages.inc
@@ -40,9 +40,9 @@ function translation_entity_overview(EntityInterface $entity) {
     // Determine whether the current entity is translatable.
     $translatable = FALSE;
     foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) {
-      $field_name = $instance['field_name'];
+      $field_name = $instance->getFieldName();
       $field = field_info_field($field_name);
-      if ($field['translatable']) {
+      if ($field->translatable) {
         $translatable = TRUE;
         break;
       }
@@ -253,7 +253,7 @@ function translation_entity_prepare_translation(EntityInterface $entity, Languag
   else {
     foreach ($instances as $field_name => $instance) {
       $field = field_info_field($field_name);
-      if (!empty($field['translatable'])) {
+      if (!empty($field->translatable)) {
         $value = $entity->get($field_name);
         $value[$target->langcode] = isset($value[$source->langcode]) ? $value[$source->langcode] : array();
         $entity->set($field_name, $value);
diff --git a/core/modules/user/lib/Drupal/user/Plugin/entity_reference/selection/UserSelection.php b/core/modules/user/lib/Drupal/user/Plugin/entity_reference/selection/UserSelection.php
index 49f00a5..ee7fb6a 100644
--- a/core/modules/user/lib/Drupal/user/Plugin/entity_reference/selection/UserSelection.php
+++ b/core/modules/user/lib/Drupal/user/Plugin/entity_reference/selection/UserSelection.php
@@ -32,7 +32,7 @@ class UserSelection extends SelectionBase {
    */
   public static function settingsForm(&$field, &$instance) {
     // Merge in default values.
-    $instance['settings']['handler_settings'] += array(
+    $instance->settings['handler_settings'] += array(
       'filter' => array(
         'type' => '_none',
       ),
@@ -48,7 +48,7 @@ public static function settingsForm(&$field, &$instance) {
       ),
       '#ajax' => TRUE,
       '#limit_validation_errors' => array(),
-      '#default_value' => $instance['settings']['handler_settings']['filter']['type'],
+      '#default_value' => $instance->settings['handler_settings']['filter']['type'],
     );
 
     $form['filter']['settings'] = array(
@@ -57,9 +57,9 @@ public static function settingsForm(&$field, &$instance) {
       '#process' => array('_entity_reference_form_process_merge_parent'),
     );
 
-    if ($instance['settings']['handler_settings']['filter']['type'] == 'role') {
+    if ($instance->settings['handler_settings']['filter']['type'] == 'role') {
       // Merge in default values.
-      $instance['settings']['handler_settings']['filter'] += array(
+      $instance->settings['handler_settings']['filter'] += array(
         'role' => NULL,
       );
 
@@ -68,7 +68,7 @@ public static function settingsForm(&$field, &$instance) {
         '#title' => t('Restrict to the selected roles'),
         '#required' => TRUE,
         '#options' => array_diff_key(user_role_names(TRUE), drupal_map_assoc(array(DRUPAL_AUTHENTICATED_RID))),
-        '#default_value' => $instance['settings']['handler_settings']['filter']['role'],
+        '#default_value' => $instance->settings['handler_settings']['filter']['role'],
       );
     }
 
@@ -133,8 +133,8 @@ public function entityQueryAlter(SelectInterface $query) {
     }
 
     // Add the filter by role option.
-    if (!empty($this->instance['settings']['handler_settings']['filter'])) {
-      $filter_settings = $this->instance['settings']['handler_settings']['filter'];
+    if (!empty($this->instance->settings['handler_settings']['filter'])) {
+      $filter_settings = $this->instance->settings['handler_settings']['filter'];
       if ($filter_settings['type'] == 'role') {
         $tables = $query->getTables();
         $base_table = $tables['base_table']['alias'];
diff --git a/core/modules/user/lib/Drupal/user/RegisterFormController.php b/core/modules/user/lib/Drupal/user/RegisterFormController.php
index ceecd65..2acf0a6 100644
--- a/core/modules/user/lib/Drupal/user/RegisterFormController.php
+++ b/core/modules/user/lib/Drupal/user/RegisterFormController.php
@@ -44,7 +44,7 @@ public function form(array $form, array &$form_state) {
     // setting is not on.
     field_attach_form($account, $form, $form_state);
     foreach (field_info_instances('user', 'user') as $field_name => $instance) {
-      if (empty($instance['settings']['user_register_form'])) {
+      if (empty($instance->settings['user_register_form'])) {
         $form[$field_name]['#access'] = FALSE;
       }
     }
diff --git a/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php b/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php
index 683bbda..ac11148 100644
--- a/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php
+++ b/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php
@@ -221,6 +221,7 @@ function testRegistrationWithUserFields() {
     // Have the field appear on the registration form.
     $instance->settings['user_register_form'] = TRUE;
     $instance->save();
+
     $this->drupalGet('user/register');
     $this->assertText($instance->label(), 'The field appears on user registration form');
 
diff --git a/core/modules/user/user.install b/core/modules/user/user.install
index 293a45e..5a21e6e3 100644
--- a/core/modules/user/user.install
+++ b/core/modules/user/user.install
@@ -798,7 +798,7 @@ function user_update_8011() {
         'fid' => $default_image_fid,
         'module' => 'image',
         'type' => 'default_image',
-        'id' => $field['uuid'],
+        'id' => $field->uuid,
         'count' => 1,
       ))
       ->execute();
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index e0ef6e6..9c352ca 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -2366,7 +2366,7 @@ function user_node_load($nodes, $types) {
 function user_form_field_ui_field_instance_edit_form_alter(&$form, &$form_state, $form_id) {
   $instance = $form_state['instance'];
 
-  if ($instance['entity_type'] == 'user') {
+  if ($instance->entity_type == 'user') {
     $form['instance']['settings']['user_register_form'] = array(
       '#type' => 'checkbox',
       '#title' => t('Display on user registration form.'),
@@ -2374,7 +2374,7 @@ function user_form_field_ui_field_instance_edit_form_alter(&$form, &$form_state,
       // Field instances created in D7 beta releases before the setting was
       // introduced might be set as 'required' and 'not shown on user_register
       // form'. We make sure the checkbox comes as 'checked' for those.
-      '#default_value' => $instance['settings']['user_register_form'] || $instance['required'],
+      '#default_value' => $instance->settings['user_register_form'] || $instance->required,
       // Display just below the 'required' checkbox.
       '#weight' => $form['instance']['required']['#weight'] + .1,
       // Disabled when the 'required' checkbox is checked.
@@ -2401,7 +2401,7 @@ function user_form_field_ui_field_instance_edit_form_alter(&$form, &$form_state,
 function user_form_field_ui_field_instance_edit_form_submit($form, &$form_state) {
   $instance = $form_state['values']['instance'];
 
-  if (!empty($instance['required'])) {
+  if (!empty($instance->required)) {
     form_set_value($form['instance']['settings']['user_register_form'], 1, $form_state);
   }
 }
diff --git a/core/modules/views/lib/Drupal/views/Plugin/entity_reference/selection/ViewsSelection.php b/core/modules/views/lib/Drupal/views/Plugin/entity_reference/selection/ViewsSelection.php
index 575c000..a3a6e2e 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/entity_reference/selection/ViewsSelection.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/entity_reference/selection/ViewsSelection.php
@@ -60,11 +60,11 @@ public function __construct(FieldDefinitionInterface $field_definition, EntityIn
    * Implements \Drupal\entity_reference\Plugin\Type\Selection\SelectionInterface::settingsForm().
    */
   public static function settingsForm(&$field, &$instance) {
-    $view_settings = empty($instance['settings']['handler_settings']['view']) ? array() : $instance['settings']['handler_settings']['view'];
+    $view_settings = empty($instance->settings['handler_settings']['view']) ? array() : $instance->settings['handler_settings']['view'];
     $displays = views_get_applicable_views('entity_reference_display');
     // Filter views that list the entity type we want, and group the separate
     // displays by view.
-    $entity_info = entity_get_info($field['settings']['target_type']);
+    $entity_info = entity_get_info($field->settings['target_type']);
     $options = array();
     foreach ($displays as $data) {
       list($view, $display_id) = $data;
diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/FieldUnitTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/FieldUnitTest.php
index 14e9197..d7560e1 100644
--- a/core/modules/views/lib/Drupal/views/Tests/Handler/FieldUnitTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/Handler/FieldUnitTest.php
@@ -74,7 +74,7 @@ public function testQuery() {
     $view = views_get_view('test_view');
     $view->initHandlers();
 
-    $id_field = $view->field['id'];
+    $id_field = $view->field->id();
     $id_field->additional_fields['job'] = 'job';
     // Choose also a field alias key which doesn't match to the table field.
     $id_field->additional_fields['created_test'] = array('table' => 'views_test_data', 'field' => 'created');
@@ -151,7 +151,7 @@ public function testRewrite() {
     $view->initHandlers();
     $this->executeView($view);
     $row = $view->result[0];
-    $id_field = $view->field['id'];
+    $id_field = $view->field->id();
 
     // Don't check the rewrite checkbox, so the text shouldn't appear.
     $id_field->options['alter']['text'] = $random_text = $this->randomName();
diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/FieldWebTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/FieldWebTest.php
index 6d73636..fc8b80c 100644
--- a/core/modules/views/lib/Drupal/views/Tests/Handler/FieldWebTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/Handler/FieldWebTest.php
@@ -180,7 +180,7 @@ public function testAlterUrl() {
     $view->initHandlers();
     $this->executeView($view);
     $row = $view->result[0];
-    $id_field = $view->field['id'];
+    $id_field = $view->field->id();
 
     // Setup the general settings required to build a link.
     $id_field->options['alter']['make_link'] = TRUE;
@@ -327,7 +327,7 @@ public function testFieldClasses() {
     $view->initHandlers();
 
     // Tests whether the default field classes are added.
-    $id_field = $view->field['id'];
+    $id_field = $view->field->id();
 
     $id_field->options['element_default_classes'] = FALSE;
     $output = $view->preview();
diff --git a/core/modules/views/lib/Drupal/views/Tests/Wizard/TaggedWithTest.php b/core/modules/views/lib/Drupal/views/Tests/Wizard/TaggedWithTest.php
index 2f870d8..c49f67e 100644
--- a/core/modules/views/lib/Drupal/views/Tests/Wizard/TaggedWithTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/Wizard/TaggedWithTest.php
@@ -188,7 +188,7 @@ function testTaggedWithByNodeType() {
     // If we add an instance of the tagging field to the second node type, the
     // "tagged with" form element should not appear for it too.
     $instance = $this->tag_instance;
-    $instance['bundle'] = $this->node_type_without_tags->type;
+    $instance->bundle = $this->node_type_without_tags->type;
     entity_create('field_instance', $instance)->save();
     entity_get_form_display('node', $this->node_type_without_tags->type, 'default')
       ->setComponent('field_views_testing_tags', array(
diff --git a/core/modules/views_ui/admin.inc b/core/modules/views_ui/admin.inc
index 02c62d8..67ed574 100644
--- a/core/modules/views_ui/admin.inc
+++ b/core/modules/views_ui/admin.inc
@@ -226,8 +226,8 @@ function views_ui_taxonomy_autocomplete_validate($element, &$form_state) {
     // vocabulary IDs.
     $field = field_info_field($element['#field_name']);
     $vocabularies = array();
-    if (!empty($field['settings']['allowed_values'])) {
-      foreach ($field['settings']['allowed_values'] as $tree) {
+    if (!empty($field->settings['allowed_values'])) {
+      foreach ($field->settings['allowed_values'] as $tree) {
         if ($vocabulary = entity_load('taxonomy_vocabulary', $tree['vocabulary'])) {
           $vocabularies[$vocabulary->id()] = $tree['vocabulary'];
         }
diff --git a/core/scripts/generate-d7-content.sh b/core/scripts/generate-d7-content.sh
index 87ec22a..8a86cef 100644
--- a/core/scripts/generate-d7-content.sh
+++ b/core/scripts/generate-d7-content.sh
@@ -98,7 +98,7 @@
   foreach ($node_types as $bundle) {
     $instance = array(
       'label' => $vocabulary->name,
-      'field_name' => $field['field_name'],
+      'field_name' => $field->id(),
       'bundle' => $bundle,
       'entity_type' => 'node',
       'settings' => array(),
